查询在SQL Server Management Studio中运行,但在sqlcmd

时间:2016-12-21 20:50:09

标签: sql sql-server sqlcmd

我编写了一个脚本,用于将数据从一个数据库复制到另一个具有(几乎)相同模式的数据库。

它在SSMS sqlcmd模式下运行良好,但是当我在sqlcmd中尝试时它失败了。

如果它有任何区别,我在cli模式下从php脚本运行sqlcmd

我已经确认这两个参数都是有效的数据库名称。

BEGIN TRANSACTION copy_data_into_existing_database;
SET XACT_ABORT ON;

DECLARE @tables TABLE (table_name VARCHAR (MAX));
DECLARE @SQL VARCHAR (MAX);

INSERT INTO @tables
    SELECT table_name
    FROM [$(source)].information_schema.tables
    WHERE table_schema = 'dbo' AND table_type = 'BASE TABLE';

/*
  Dynamically generate the query for each table in the list
  The query template is
    - truncate the table
    - if the table has an identity SET IDENTITY_INSERT ON
    - INSERT INTO the destination DB with a list of all of the columns
    - SELECT FROM the source DB with a list of all of the columns
    - if the table has an identity SET IDENTITY_INSERT OFF
 */
SET @SQL =
(SELECT
  -- this line is the truncate statement
 'TRUNCATE TABLE [$(dest)].dbo.' + table_name + ';' +
 -- this case statement sets the identity insert if the table has an identity
  CASE WHEN (EXISTS(SELECT t.object_id
                    FROM [$(dest)].sys.tables t
                      INNER JOIN [$(dest)].sys.identity_columns ic ON t.object_id = ic.object_id
                    WHERE t.name = table_name))
  THEN 'SET IDENTITY_INSERT [$(dest)].dbo.' + table_name + ' ON;'
        ELSE '' END +
        -- this line is the insert statement, the substring-select gets a CSV of all non-computed columns for this table
        'INSERT INTO [$(dest)].dbo.' + table_name + '(' + SUBSTRING((SELECT ',' + c.name
                                                                      FROM [$(source)].sys.columns c
                                                                      INNER JOIN [$(source)].sys.tables t
                                                                        ON c.object_id = t.object_id
                                                                      WHERE is_computed = 0
                                                                        AND t.name = table_name
                                                                      FOR XML PATH ('')), 2, 99999) + ') ' +
        -- this line is the select statement, it repeats the same substring-select from the previous line
        'SELECT ' + SUBSTRING((SELECT ',' + c.name
                                FROM [$(source)].sys.columns c
                                INNER JOIN [$(source)].sys.tables t ON c.object_id = t.object_id
                                WHERE is_computed = 0 AND t.name = table_name
                               FOR XML PATH ('')), 2, 99999) + ' ' +
        'FROM [$(source)].dbo.' + table_name + ';' +
        -- this case statement sets the identity insert off it the table has an identity
        CASE WHEN (EXISTS(SELECT t.object_id
                          FROM [$(dest)].sys.tables t
                           INNER JOIN [$(dest)].sys.identity_columns ic ON t.object_id = ic.object_id
                          WHERE t.name = table_name))
          THEN 'SET IDENTITY_INSERT [$(dest)].dbo.' + table_name + ' OFF;'
        ELSE '' END
 FROM @tables tl
 FOR XML PATH (''));

SELECT (@SQL);
SET @SQL = 'SET NOEXEC ON;' + @SQL; --DEBUG
EXECUTE (@SQL);


COMMIT TRANSACTION copy_data_into_existing_database;

当我在sqlcmd中运行它时会出现一堆语法错误。

  

Msg 102,Level 15,State 1,Server INTERNAL \ INTERNAL,Line 24
  '。。。dbo'附近的语法不正确。

     

消息102,级别15,状态1,服务器内部\内部,第29行
  ')'附近的语法不正确。

     

消息156,级别15,状态1,服务器内部\内部,第39行
  关键字“FOR”附近的语法不正确。

     

消息156,级别15,状态1,服务器内部\内部,第45行
  关键字“FOR”附近的语法不正确。

     

Msg 102,Level 15,State 1,Server INTERNAL \ INTERNAL,Line 51
  ')'附近的语法不正确。

1 个答案:

答案 0 :(得分:1)

问题在于字符串是双引号。我在命令行输入了这个:

sqlcmd -Sinternal\internal -iV:\inventory2-temp-rollout\MigrationHelpers\CopyDataIntoEx‌​istingDb.sql -v source="'products_live'" -v dest="'products'"

我删除了单引号:

sqlcmd -Sinternal\internal -iV:\inventory2-temp-rollout\MigrationHelpers\CopyDataIntoEx‌​istingDb.sql -v source="products_live" -v dest="products"