Cursor和动态SQL中的语法错误

时间:2017-03-23 19:09:02

标签: sql-server syntax cursor dynamic-sql

我的以下代码给出了错误:(SQL Server 2008R2;在游标中获取两个数据库名称,然后在两个数据库中将数据插入Table1)

DECLARE @SQL NVARCHAR(max)
DECLARE @DB  VARCHAR(50)

DECLARE CUR_DB CURSOR FAST_FORWARD FOR 
        SELECT NAME FROM MASTER.SYS.DATABASES
        WHERE DATABASE_ID IN ('5', '81')
;

OPEN CUR_DB;
FETCH NEXT FROM CUR_DB INTO @DB;

WHILE @@FETCH_STATUS = 0 
BEGIN
    SELECT @SQL = 'INSERT INTO @DB.dbo.Table1 VALUES (100, ''abc'', def'', 0)'
    EXEC(@SQL)
    FETCH NEXT FROM CUR_DB INTO @DB 
END;

CLOSE CUR_DB;
DEALLOCATE CUR_DB;
  

错误:消息102,级别15,状态1,行1'附近的语法不正确。'。   消息102,级别15,状态1,行1错误的语法附近'。'。

3 个答案:

答案 0 :(得分:1)

您没有在动态SQL中连接数据库的名称:

DECLARE @SQL NVARCHAR(max)
DECLARE @DB  VARCHAR(50)

DECLARE CUR_DB CURSOR FAST_FORWARD FOR 
        SELECT NAME FROM MASTER.SYS.DATABASES
        WHERE DATABASE_ID IN ('5', '81')
;

OPEN CUR_DB;
FETCH NEXT FROM CUR_DB INTO @DB;

WHILE @@FETCH_STATUS = 0 
BEGIN
    SELECT @SQL = 'INSERT INTO ' + QUOTENAME(@DB) + '.dbo.Table1 VALUES (100, ''abc'', def'', 0)'
    EXEC(@SQL)
    FETCH NEXT FROM CUR_DB INTO @DB 
END;

CLOSE CUR_DB;
DEALLOCATE CUR_DB;

答案 1 :(得分:0)

为什么要使用游标?您将此限制为仅限于两个数据库。为什么不将它编码为两个插入语句,并用光标忘记所有的疯狂。整个游标结构真的很简单。

INSERT INTO DataBaseNameForDataBaseID5.dbo.Table1 VALUES (100, 'abc', 'def', 0)
INSERT INTO DataBaseNameForDataBaseID81.dbo.Table1 VALUES (100, 'abc', 'def', 0)

--- --- EDIT

既然你说你需要在这两个以上的数据库上执行此操作,那么你仍然不需要使用游标来做这类事情。看看这个。它使用动态sql,但不需要循环。

declare @SQL nvarchar(MAX) = N''

select @SQL = @SQL + N'INSERT INTO ' + QuoteName(name) + N'.dbo.Table1 VALUES (100, ''abc'', ''def'', 0);'
from sys.databases
where DATABASE_ID IN (5, 81) --No quotes here, these are integers, not strings

exec sp_executesql @SQL

答案 2 :(得分:0)

请尝试以下脚本

DECLARE @SQL NVARCHAR(max)
DECLARE @DB  VARCHAR(50)

DECLARE CUR_DB CURSOR FAST_FORWARD FOR 
    SELECT NAME FROM MASTER.SYS.DATABASES
    WHERE DATABASE_ID IN ('5', '81');

OPEN CUR_DB;
FETCH NEXT FROM CUR_DB INTO @DB;

WHILE @@FETCH_STATUS = 0 
BEGIN
    SELECT @SQL = 'INSERT INTO ['+@DB+'].[dbo].[Table1] VALUES (100,''abc'',''def'', 0)'
    EXEC( @SQL)
    FETCH NEXT FROM CUR_DB INTO @DB 
END;

CLOSE CUR_DB;
DEALLOCATE CUR_DB;

脚本中有2个问题:

  1. 您在查询字符串

    中使用了参数名称
    'INSERT INTO **@DB**.dbo.Table1 VALUES (100, ''abc'', def'', 0)'
    
  2. 这将导致错误,因为EXEC语句将括号内给出的所有语句作为单独的批处理运行,并且在此之前声明的参数都不在EXEC语句的范围之外。所以改为将其改为

         SELECT @SQL = 'INSERT INTO **['+@DB+']**.[dbo].[Table1] VALUES (100, ''abc'', ''def'', 0)'
    
    1. 在值def

      之前缺少2个单引号
       VALUES (100, ''abc'', **def''**, 0)'
      
    2. 所以我刚才补充说。

      希望有所帮助。