我需要构建一个查询,以选择根据某些条件而有所不同的表达式
DECLARE @program NVARCHAR(22) = 'test';
DECLARE @result NVARCHAR(10);
DECLARE @currency_results NVARCHAR(200) = '';
DECLARE @sql NVARCHAR(MAX)
--where program = @program ) and currncy = 'T';
DECLARE results CURSOR FAST_FORWARD FOR
SELECT result
FROM calcresult
WHERE calcfile = (SELECT calc_file
FROM program
WHERE program = @program)
AND currncy = 'T';
OPEN results;
FETCH NEXT FROM results INTO @result;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @currency_results = @currency_results + '+' + @result ;
PRINT @currency_results
FETCH NEXT FROM results INTO @result
END
PRINT @currency_results
CLOSE results;
DEALLOCATE results;
SET @sql = 'SELECT ' + @currency_results + ' FROM tphase WHERE program = @program';
EXEC (@sql);
初始化@currency_results
解决了最后一个问题。但是,现在我遇到了某种范围错误:
第1级第15行第2行137消息
必须声明标量变量“ @program”
答案 0 :(得分:0)
您已在构建SQL字符串的外部过程代码中声明了@program,但这并不意味着它在执行SQL时创建的作用域中可用。将@prgram声明放入您构建的sql字符串(您执行的那个)中
SET @sql = 'declare @program nvarchar(10) = ''' + @program + ''';
select ' + @currency_results + ' from tphase where program = @program';
或者抛弃它,然后将任何值放在程序中的字符串sql中:
SET @sql = 'select ' + @currency_results + ' from tphase where program = ''' + @program + '''';
如果用户提供@program的值,请注意是否进行了sql注入-使用适当的方法来防止它注入-有关如何使用sp_executesql来运行参数化动态sql的信息,请参见https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql?view=sql-server-2017。它可能看起来像这样:
SET @sql = 'select ' + @currency_results + ' from tphase where program = @prog';
sp_executesql @sql, '@prog nvarchar(10)', @prog = @program;
我特意将其称为@prog和@program,以更清楚地显示变量“活动”的位置(prog仅存在于对sp_executesql的调用中,而程序仅存在于其外部)
附带说明,如果您不希望使用null值来使整个字符串为空,则使用CONCAT函数来连接字符串更为有用:
'A' + null + 'b' -- result: null string
CONCAT('A', null, 'b') -- result: Ab