【问题标题】:Msg 102, Level 15, State 1, Line 3 Incorrect syntax near ' ' with sp_executesql消息 102,级别 15,状态 1,第 3 行使用 sp_executesql 的“”附近的语法不正确
【发布时间】:2021-02-28 04:35:39
【问题描述】:

我正在根据来自几个不同表的操作动态构建 SQL 语句。 SQL 的重点部分如下。

DECLARE @SQL NVARCHAR(MAX) = NULL
...
SELECT @sql = 'TRIM(CAST(' + STRING_AGG(EXPORT_COL, ' AS VARCHAR)) + '','' + TRIM(CAST(') FROM #TEMP_TABLE
SET @sql = 'SELECT''(''+'+@sql+' AS VARCHAR))+'')'''+'FROM '+'[mydatabase].[dbo].['+@TABLENAME+']'
SET @sql = REPLACE(@sql,'''','''''')

当我使用sp_executesql调用代码时

EXEC sp_executesql @sql

我收到此错误

消息 102,第 15 级,状态 1,第 1 行
''

附近的语法不正确

如果我查询 @sql 或将值打印到 SSMS 中的消息窗口,我会得到:

SELECT''(''+TRIM(CAST(COL1 AS VARCHAR)) + '','' + TRIM(CAST(COL2 AS VARCHAR))+'')''FROM [mydatabase].[dbo].[DATA_TABLE] 

这是我期望的输出。

复制文本并使用带引号的输出字符串调用sp_executesql,查询成功且没有错误。

EXEC sp_executesql N'SELECT''(''+TRIM(CAST(COL1 AS VARCHAR)) + '','' + TRIM(CAST(COL2 AS VARCHAR))+'')''FROM [mydatabase].[dbo].[DATA_TABLE]'

我已经检查了此post 中指示的不可打印字符的存在

我还实现了一个函数,该函数“应该”根据 post 删除任何不可打印的字符。然而问题依然存在。

Windows Server 2019 标准上的 SQL Server 2017 Express (v14.0.1000.169)。

【问题讨论】:

  • PRINT 您的动态 SQL 并首先对其进行调试,然后将解决方案移至动态语句。
  • 另外'['+@TABLENAME+']'不安全注射。使用QUOTENAME 安全地注入对象名称。
  • @Larnu 这是我在调试期间做的第一件事。动态 SQL 打印复制成功。
  • 那么也将它发送到sys.sp_executesql。花点时间在这里给我们打个minimal reproducible example

标签: sql-server syntax-error ssms


【解决方案1】:

您需要非常小心何时以及哪些部分需要单引号,哪些部分需要双引号。

如果您正在编写字符串以将其分配给变量,则它需要双引号。但是,如果字符串中已经包含引号,则不需要再次加倍。

这是一个显示问题/方法的简化示例

CREATE TABLE #Test (TestVal varchar(100));
INSERT INTO #Test (TestVal) VALUES ('abcde');

现在,当使用双引号(与您的类似)运行该过程时,结果如下

DECLARE @SQL2 nvarchar(max) = 'SELECT ''''('''' + TestVal + '''')'''' FROM #Test;'
PRINT @SQL2;
/* -- Result
SELECT ''('' + TestVal + '')'' FROM #Test;
*/

EXEC sp_executesql @SQL2;
/* -- Result
Msg 102, Level 15, State 1, Line 12
Incorrect syntax near ''.
*/

EXEC sp_executesql N'SELECT ''('' + TestVal + '')'' FROM #Test;';
/* -- Result
(abcde)
*/

请注意,在底部命令中,需要双引号,以便字符串包含单引号 - 因此可以工作。但是,当已经在字符串中时,它会使命令失败。

现在,如果我们让变量只有单引号,它就可以工作

DECLARE @SQL3 nvarchar(max) = 'SELECT ''('' + TestVal + '')'' FROM #Test;'
PRINT @SQL3;
/* -- Result
SELECT '(' + TestVal + ')' FROM #Test;
*/

EXEC sp_executesql @SQL3;
/* -- Result
(abcde)
*/

【讨论】:

  • 你的例子正是正在发生的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 2018-06-19
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
相关资源
最近更新 更多