【问题标题】:Dynamic sql is giving syntax error.动态 sql 给出语法错误。
【发布时间】:2014-01-30 22:58:27
【问题描述】:

我正在执行以下 sql。我收到一个语法错误('=' 附近的语法不正确) 查询执行良好,并在正常执行时给出正确的结果。无法理解。请看一下。

DECLARE @pvchMachineId VARCHAR(100)  = ''

DECLARE @pvchMake VARCHAR(100) = ''

DECLARE @sql NVARCHAR(1000)

SELECT @sql = ' SELECT TOP 20 x.intId, x.vchMachineId, x.AUDenom, x.intGroupId,

x.vchMake, x.vchModel, x.mCurrency

from dbo.Machine x

inner join
(select max(m1.AUDenom) as audenom, m1.vchMachineId

from dbo.Machine m1
left JOIN dbo.ImportedFile ife on m1.intImportedFileId = ife.intId
WHERE ife.dtFileDate >= ''1-1-2013'' AND ife.dtFileDate <= ''1-29-2014'' AND

--following two lines cause the error

(' + @pvchMake + '= ''0'' OR m1.vchMake = @pvchMake) AND

(' + @pvchMachineId +'= ''0'' OR m1.vchMachineId = @pvchMachineId)

group by vchMachineId) y

on x.AUDenom = y.audenom and x.vchMachineId = y.vchMachineId 
ORDER BY x.AUDenom DESC'

【问题讨论】:

  • 你的变量的值是多少?
  • 你是如何传递这些参数来执行语句的?
  • 您能否显示查询的非动态版本。这有助于理解您的意思。
  • 检查动态sql的最好方法是在最后一行使用SELECT @sql
  • sql 中带有-- 的注释在行结束时结束。动态sql也是一样。

标签: sql sql-server tsql


【解决方案1】:

将您的查询更新为以下内容

(@pvchMake = ''0'' OR m1.vchMake = @pvchMake) AND
(@pvchMachineId = ''0'' OR m1.vchMachineId = @pvchMachineId)

稍后当您执行时,只需将其作为参数传递给 sp_executesql 函数即可。

EXEC sp_executesql @sql
         ,N'@pvchMachineId VARCHAR(100), @pvchMake VARCHAR(100)'
         ,@pvchMachineId,@pvchMake

或者这个更干净

Declare @ParametersDefinition NVARCHAR(max) = N'@pvchMachineId VARCHAR(100), @pvchMake VARCHAR(100)'
EXEC sp_executesql @sql, @ParametersDefinition, @pvchMachineId,@pvchMake

最后,您不想连接动态 SQL 语句,它为 SQL 注入打开了大门。即使这是一个有效的选择,也应该不惜一切代价避免。

【讨论】:

  • 我也从应用程序中执行了它。它工作正常
【解决方案2】:

此声明:

'(' + @pvchMake + '= ''0'' OR m1.vchMake = @pvchMake)'

将输出,因为变量没有被''以外的任何东西初始化:

(= '0' OR m1.vchMake = @pvchMake)

这在语法上是不正确的。

你应该使用:

'(''' + @pvchMake + '''= ''0'' OR m1.vchMake = @pvchMake)'

哪个会输出:

(''= '0' OR m1.vchMake = @pvchMake)

【讨论】:

  • 如果我希望 OR 运算符短路,我会从应用程序发送一个 0 或 ''。如果需要匹配,我会发送一个字符串值。
【解决方案3】:

也许这是有道理的:

...

(''' + @pvchMake + '''= ''0'' OR m1.vchMake = ''' + @pvchMake +''') AND

(''' + @pvchMachineId +'''= ''0'' OR m1.vchMachineId = ''' + @pvchMachineId + ''')
...

【讨论】:

  • +1 @THunter 或者您可以发送 '''' 而不是 ''
  • @THunter,如果您想将@pvchMake@pvchMake 作为参数传递,可以使用@SaUce 解决方案。
  • @HamletHakobyan。我犯了一个语法错误,修改后它工作得很好
猜你喜欢
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 2021-10-23
  • 1970-01-01
相关资源
最近更新 更多