首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在sql server中,如果我使用exec语句在过程中运行动态sql,如何将结果作为输出参数检索?

问在sql server中,如果我使用exec语句在过程中运行动态sql,如何将结果作为输出参数检索?
EN

Stack Overflow用户
提问于 2015-08-12 12:23:42
回答 1查看 69关注 0票数 0

我不确定我的问题是否写得很好,我肯定以前有人问过,但我没有找到.

在proc中,我使用EXEC创建和运行一些动态SQL来创建一个大型CSV字符串。问题是,如果我将结果放入到EXEC中的nvarchar(max)变量中,那么它不在PROC范围内,那么如何通过过程中的输出变量获得返回它的值?

我猜我不知怎么搞错了这件事:哦)

下面是我的实际代码(如果需要的话,我可以生成一个不那么复杂的示例,并解释为什么它是复杂的):

代码语言:javascript
复制
CREATE PROCEDURE GETFORMDATACSV 
(
    -- Add the parameters for the function here
    @FORMID numeric(38,0), 
    @STARTDATE nvarchar(20) = '1900-01-01',
    @ENDDATE nvarchar(20)   = '2100-01-01'--,
    --@RCSV nvarchar(max)    OUTPUT
)

AS 
BEGIN 
DECLARE @CSV nvarchar(max);
DECLARE @CRLF nchar(2) = char(13) + char(10);
DECLARE @FIELDS nvarchar(4000);         -- list of fields comma delimited
DECLARE @FIELDSDL nvarchar(4000);       -- list of fields "", delimited
DECLARE @FIELDSSEL nvarchar(4000);      -- list of fields with replace " with ' if needed
DECLARE @SEP nchar(1); 
DECLARE @SELSEP nvarchar(20);
DECLARE @SQL nvarchar(2000);
DECLARE @FCSV nvarchar(max);


set @SEP = ''; 
set @SELSEP = ',''","'','; 

select  @FIELDS =  isnull(@FIELDS,'') + @SEP + isnull(FD,'''x'''), 
@FIELDSDL =   isnull(@FIELDSDL,'')  + @SEP + '"' + isnull(FD,'''x''') + '"',
@FIELDSSEL =  isnull(@FIELDSSEL,'') + @SELSEP + 'replace(' + isnull(FD,'''x''') + ',''"'','''''''')',
@SEP = ','   
from (select distinct rf.FIELD as FD from FORMRESPONSEFIELDS rf  
JOIN FORMRESPONSE r on r.ID = rf.ID  
where r.FORMID = @FORMID and r.RDATE between cast(@STARTDATE as date) and cast(@ENDDATE as date)) x; 

if len(@FIELDS) > 0  
 BEGIN 
  set @CSV = '"RESPID","RDATE",' + @FIELDSDL ;
  set @SQL = 'DECLARE @FCSV nvarchar(max); set @FCSV = ''' + @CSV + @CRLF +  '''; select @FCSV = isnull(@FCSV,'''') + concat(''"'',RESPID,''","'', RDATE' + @FIELDSSEL + ',''"'',char(13),char(10)) from (select ID as RESPID, RDATE, ' + isnull(@FIELDS,'')  
  set @SQL = @SQL + ' from (select a.ID, FIELD, VALUE, RDATE from FORMRESPONSEFIELDS a JOIN FORMRESPONSE b on a.ID = b.ID ' 
  set @SQL = @SQL + ' where b.FORMID = ' + cast(@FORMID as nvarchar(15)) + ' and b.RDATE between cast(''' + @STARTDATE  + '''as nvarchar(20)) and cast(''' + @ENDDATE + ''' as nvarchar(20))) rf '; 
  set @SQL = @SQL + ' pivot ( max(VALUE)  for FIELD in (' + isnull(@FIELDS,'') + ')) as pvt)x order by RDATE desc; select @FCSV; '; 
 END; 
ELSE 
 BEGIN 
  set @SQL = 'select ''No Data available for FORMID = ' + cast(@FORMID as nvarchar(15)) + ' between ' + @STARTDATE + ' and ' + @ENDDATE + ' '''; 
 END; 
EXEC(@SQL); 
RETURN;
END;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-12 12:28:22

使用sp_executesql而不是EXEC(),从动态SQL中删除声明,并传递输出参数。一个简单的例子是:

代码语言:javascript
复制
DECLARE @SQL NVARCHAR(MAX) = 'SELECT @i = 1;';
DECLARE @i INT;
EXECUTE sp_executesql @SQL, N'@i INT OUTPUT', @i OUTPUT;

SELECT  @i;

在查看了动态SQL之后,您还应该使用输入参数,因此,而不是:

代码语言:javascript
复制
set @SQL = @SQL + ' where b.FORMID = ' + cast(@FORMID as nvarchar(15)) + ' ...'

简单地使用

代码语言:javascript
复制
SET @SQL = @SQL + ' WHERE b.FormID = @FormID '

然后将@FormID传递给sp_executesql:

代码语言:javascript
复制
EXECUTE sp_executesql @SQL, N'@FormID INT, @i INT OUTPUT', @FormID, @i OUTPUT;

增编

在您的日期中使用输入参数更重要,您有:

代码语言:javascript
复制
SET @SQL = @SQL + ' and b.RDATE between cast(''' + @STARTDATE  + '''as nvarchar(20)) and cast(''' + @ENDDATE + ''' as nvarchar(20))) rf ';  

这是显式地将@StartDate (由于某种原因实际上是nvarchar )转换为NVARCHAR(20),只是隐式地将其转换为与b.RDATE进行比较的日期。这只是要求转换错误!将@StartDate和@EndDate参数设置为DATETIME类型,并再次在动态SQL中使用参数:

代码语言:javascript
复制
SET @SQL = @SQL + ' WHERE b.FormID = @FormID AND b.RDate BETWEEN @StartDate AND @EndDate ';
EXECUTE sp_executesql 
        @SQL, 
        N'@FormID NUMERIC(38,0), @StartDate DATETIME2, @EndDate DATETIME2', 
        @FormID,
        @StartDate,
        @EndDate;

现在,您有了字符串类型的参数,不会被转换错误或格式错误的sql所困扰。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31965131

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档