查询字符串的变量

时间:2016-11-29 09:58:06

标签: sql sql-server tsql dynamic-sql

由于等级较高的论坛用户建议我将我的问题作为与此问题相关的新问题:declare variable for query string

我在这里使用动态查询因为我希望能够使用变量(我需要它用于涉及参数嗅探的实验)。我的查询如下:

TextField

当我想执行我的查询时,我得到的错误如下:

DECLARE @i NVARCHAR(10)
SET @i = 'POL'

DECLARE @sql VARCHAR(MAX)
SET @sql = 'SELECT

a.something1,
b.something2,
c.something3

FROM
aaa a WITH(NOLOCK)
LEFT JOIN bbb b WITH(NOLOCK) ON....
LEFT JOIN ccc c WITH(NOLOCK) ON....

WHERE
a.somethingelse = ''aa''
AND
((a.entirelysomethingelse=''aaa'') OR (a.entirelysomethingelse=''aaaa''))
AND
b.anotherdifferentsomething != 41
AND 
c.yetanotherdifferentthing LIKE(''%@%'')
AND
c.datafromvariablewannabe = (@i)
GROUP BY
...
ORDER BY
...'
EXECUTE (@SQL)

当我将变量@i的声明移到@sql中时,它的排序是有效的。我仍然不认为这是我想要的。我做错了什么或看起来像这样?:

'Msg 137, Level 15, State 2, Line 28
Must declare the scalar variable "@i".'

我的代码是否有任何错误,因此我收到了MSG137错误,或者我想在这里完成这项任务。

我不想从此查询中创建存储过程。我希望能够使用变量但不依赖于存储过程。

我向管理员/论坛用户道歉,因为我在超链接问题中涉及我之前的问题。

2 个答案:

答案 0 :(得分:2)

你需要"打破"字符串。值@i在执行字符串的范围内不可用,因此您需要将其作为字符串的一部分。 像这样:

DECLARE @tmp NVARCHAR(10)
SET @tmp = 'POL'

DECLARE @sql VARCHAR(MAX)
SET @sql = 'SELECT

a.something1,
b.something2,
c.something3

FROM
aaa a WITH(NOLOCK)
LEFT JOIN bbb b WITH(NOLOCK) ON....
LEFT JOIN ccc c WITH(NOLOCK) ON....

WHERE
a.somethingelse = ''aa''
AND
((a.entirelysomethingelse=''aaa'') OR (a.entirelysomethingelse=''aaaa''))
AND
b.anotherdifferentsomething != 41
AND 
c.yetanotherdifferentthing LIKE(''%@%'')
AND
c.datafromvariablewannabe = (@i)
GROUP BY
...
ORDER BY
...
OPTION(OPTIMIZE FOR(@i = ''' + @tmp + '''))'
EXEC SP_EXECUTESQL @SQL, N'@i NVARCHAR(255)', @i = @tmp

答案 1 :(得分:1)

对@variable进行优化的工作解决方案看起来像这样:

DECLARE @i NVARCHAR(255)
declare @tmp nvarchar(255)
SET @tmp = 'POL'

DECLARE @SQL nVARCHAR(MAX)
SET @sql = 'SELECT

a.something1,
b.something2,
c.something3

FROM
aaa a WITH(NOLOCK)
LEFT JOIN bbb b WITH(NOLOCK) ON....
LEFT JOIN ccc c WITH(NOLOCK) ON....

WHERE
a.somethingelse = ''aa''
AND
((a.entirelysomethingelse=''aaa'') 
OR 
(a.entirelysomethingelse=''aaaa''))
AND
b.anotherdifferentsomething != 41
AND 
c.yetanotherdifferentthing LIKE(''%@%'')
AND
c.datafromvariablewannabe = (@i)

GROUP BY
...
ORDER BY
...

OPTION(OPTIMIZE FOR(@i = ''' + @tmp + '''))'

EXECUTE SP_EXECUTESQL @SQL, N'@i NVARCHAR(255)', @i = @tmp

如果没有声明变量@temp,它就无法工作。之后我遇到了Exec的问题。 @mortb建议,我无法使用SP_EXECUTESQL。我必须在EXECUTE之前使用SP_EXECUTESQL,我在帖子Why do I get "Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'." when I try to use sp_executesql?中找到了与下一个错误相关的一些信息。我不得不更改查询变量的类型并删除括号。

我仍然想知道为什么我必须创建新变量,这对于了解这部分代码更有帮助:

OPTION(OPTIMIZE FOR(@i = ''' + @tmp + '''))'

EXECUTE SP_EXECUTESQL @SQL, N'@i NVARCHAR(255)', @i = @tmp

它现在有效,但我想知道原因和方法?