如何在 SQL 服务器中使用 bcp 运行 .sql 文件

How to run a .sql file using bcp in SQL Server

我是处理 SQL 服务器批量导出的新手。我有一个批处理文件,我在其中编写了一些代码以定期执行特定的 .sql 文件并将输出保存到 excel sheet 中。我使用 sqlcmd 完成了此操作。我想使用 bcp 来做同样的事情。非常感谢对此问题的任何帮助。

Hafsa Mushtaq。

最好的选择是 powershell - 您可以使用这个很棒的 dbatools 功能来导入您的数据 https://github.com/sqlcollaborative/dbatools/blob/development/functions/Import-DbaCsvToSql.ps1 and my script to Export https://github.com/ktaranov/sqlserver-kit/blob/master/PowerShell/Export-SQLTableToCSV.ps1

或者你可以使用动态sql生成所有语句然后执行它。 下面的所有存储过程都需要解决 SQL 服务器中 bcp 和 BULK INSERT 的一些限制 - bcp 无法创建具有 header 的文件,并且 BULK INSERT 无法导入具有 IDENTITY 列的表。

使用 bcp 实用程序和我的存储过程将所有表卸载到 csv usp_bcpTableUnload and usp_PrintString:

DECLARE @tsqlCommand NVARCHAR(MAX) = '';
DECLARE @path NVARCHAR(900) = 'd:1\NIIGAZ3\';
DECLARE @databaseName  SYSNAME = 'NIIGAZ';
DECLARE @exludeColumns NVARCHAR(MAX) = '';  -- '[CreatedDate],[ModifiedDate],[UserID]';
DECLARE @codePage NVARCHAR(10) ='C65001';  -- '1251'
DECLARE @crlf NVARCHAR(10) = CHAR(13);
DECLARE @debug BIT = 1;

IF @debug = 0 SET NOCOUNT ON;


SELECT @tsqlCommand = @tsqlCommand + 'EXECUTE dbo.usp_bcpTableUnload @databaseName   = ''' + @databaseName + ''','              + @crlf +
                                     '                               @path           = ''' + @path + ''','                      + @crlf + 
                                     '                               @schemaName     = ''' + SCHEMA_NAME(t.[schema_id]) + ''',' + @crlf +
                                     '                               @tableName      = ''' + t.[name]        + ''','            + @crlf +
                                     '                               @excludeColumns = ''' + @exludeColumns  + ''','            + @crlf +
                                     '                               @codePage       = ''' + @codePage       + ''','            + @crlf +
                                     '                               @formatFile     = ''xml'';'                                + @crlf
FROM [sys].[tables] t
INNER JOIN [sys].[dm_db_partition_stats] ps
     ON ps.[object_id] = t.[object_id]
WHERE [index_id] < 2  -- AND SCHEMA_NAME(t.[schema_id]) IN ()
GROUP BY t.[name]
        ,t.[schema_id]
HAVING SUM(ps.[row_count]) > 1
--ORDER BY 1, 2 ASC
OPTION (RECOMPILE);

IF @debug = 1
BEGIN
    EXEC dbo.usp_PrintString @str = @tsqlCommand;
END;

IF @debug = 0
BEGIN
EXEC sp_executesql @tsqlCommand;
END

要将此文件批量插入数据库,您可以使用此代码和存储过程 usp_BulkUpload:

DECLARE @debug BIT = 0;
DECLARE @tsqlCommand NVARCHAR(max) = '';
DECLARE @path NVARCHAR(1000) = '$(varPath)txt\';  -- 'd:\NII\SQL\txt\';
DECLARE @ExcludeColumns NVARCHAR(1000) = '';  -- 'CreatedDate,ModifiedDate,UserID';
DECLARE @firstRow INTEGER = 2;
DECLARE @fieldTerminator NVARCHAR(10) = '''|''';
DECLARE @crlf NVARCHAR(10) = CHAR(13);

WITH fk_tables AS (
SELECT  s1.name AS from_schema
      , o1.name AS from_table
      , s2.name AS to_schema
      , o2.name AS to_table
FROM sys.foreign_keys fk
INNER JOIN sys.objects o1 ON fk.parent_object_id = o1.object_id
INNER JOIN sys.schemas s1 ON o1.schema_id = s1.schema_id
INNER JOIN sys.objects o2 ON fk.referenced_object_id = o2.object_id
INNER JOIN sys.schemas s2 ON o2.schema_id = s2.schema_id
/*For the purposes of finding dependency hierarchy
    we're not worried about self-referencing tables*/
WHERE NOT (s1.name = s2.name
       AND o1.name = o2.name
  )
)
, ordered_tables AS (
SELECT   s.name AS schemaName
       , t.name AS tableName
       , 0 AS table_level
FROM sys.tables AS t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
LEFT JOIN fk_tables fk ON s.name = fk.from_schema
 AND t.name = fk.from_table
WHERE fk.from_schema IS NULL
UNION ALL
SELECT fk.from_schema
 ,fk.from_table
 ,ot.table_level + 1
FROM fk_tables fk
INNER JOIN ordered_tables ot ON fk.to_schema = ot.schemaName
 AND fk.to_table = ot.tableName
)
,final AS (
SELECT DISTINCT ot.schemaName
 ,ot.tableName
 ,ot.table_level
FROM ordered_tables ot
INNER JOIN (
 SELECT schemaName
  ,tableName
  ,MAX(table_level) maxLevel
 FROM ordered_tables
 GROUP BY schemaName
  ,tableName
 ) mx ON ot.schemaName = mx.schemaName
 AND ot.tableName = mx.tableName
 AND mx.maxLevel = ot.table_level
)
SELECT @tsqlCommand = @tsqlCommand +
      'EXECUTE     dbo.usp_BulkUpload @path            = ''' + @path + ''', '                  + @crlf +
      '                               @fileName        = ''' + QUOTENAME(final.schemaName) + '.' + QUOTENAME(final.tableName) + ''', ' + @crlf +
      '                               @fileExtension   = ''txt'', '                            + @crlf +
      '                               @databaseName    = ''NIIGAZ'', '                         + @crlf +
      '                               @schemaName      = ''' + final.schemaName + ''', '       + @crlf +
      '                               @tableName       = ''' + final.tableName + ''', '        + @crlf +
      '                               @FIRSTROW        = ' + CAST(@firstRow AS NVARCHAR) + ',' + @crlf +
      '                               @CODEPAGE        = ' + N'65001' + ' ,'                        + @crlf +
      '                               @useIdentity     = ' + CASE WHEN OBJECTPROPERTY(OBJECT_ID(schemaName + '.' + tableName), 'TableHasIdentity') = 1
                                                                  THEN '1' ELSE '0'
                                                             END + ' ,'                        + @crlf +
      '                               @FIELDTERMINATOR = ' + @fieldTerminator + ',' + @crlf +
      '                               @ROWTERMINATOR   = ''' + CASE WHEN final.tableName IN ('PowerPlant', 'Turbine', 'EnergoBusinessArticle') THEN N'0x0a'''
                                                                ELSE '\n'''
                                                           END + ' ,'            + @crlf +
      '                               @excludeColumns  = ''' + @ExcludeColumns + ''';'         + @crlf
  FROM final
 WHERE (
           final.schemaName NOT IN ('dbo')
           AND final.tableName NOT IN (
                 'ExcludeYourTable'
           )
           AND final.tableName NOT LIKE '%Temp'
      )
      OR final.tableName IN ('IncludeYourTable')
      OR final.tableName LIKE 'AspNet%'
      OR final.tableName LIKE 'Application%'
ORDER BY table_level;

IF @debug = 1 EXECUTE dbo.usp_PrintString @str = @tsqlCommand;
IF @debug = 0 EXECUTE sp_executesql @tsqlCommand;

使用-s "|"使用 sqlcmd。这应该允许您使用由制表符分隔的字段输出数据。

-s 用于列分隔符。

sqlcmd Utility