【问题标题】:SQL Server format file - can I use to generate create table statement?SQL Server 格式文件 - 我可以用来生成创建表语句吗?
【发布时间】:2018-02-18 10:37:15
【问题描述】:

我收到了 35 个 SQL Server 格式文件(xml 和非 xml)和相关的数据文件。我没有创建 35 个表所需的 DDL。

有没有办法对格式文件进行逆向工程以生成创建表语句?我知道我可以查看每个文件并手动执行此操作,但尝试查看是否有更简单的方法...

【问题讨论】:

  • 当然有。 XML 格式文件将是最简单的。你有数据类型和它们的长度......因此你有表格。创建一个格式文件-Creating an XML Format File | Microsoft Docs整个页面会帮助你
  • 对于非 xml,您只需将它们粘贴到 Excel 中并使用公式为您生成代码。粗鲁,但有效。
  • 你能把格式文件放在我们可以访问的地方吗?

标签: sql-server xml reverse-engineering ddl bcp


【解决方案1】:

假设您的 bcp xml 格式文件与此类似:

<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RECORD>
  <FIELD ID="1" xsi:type="NativeFixed" LENGTH="4"/>
  <FIELD ID="2" xsi:type="NativePrefix" PREFIX_LENGTH="1"/>
  <FIELD ID="3" xsi:type="CharPrefix" PREFIX_LENGTH="2" MAX_LENGTH="3" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
  <FIELD ID="4" xsi:type="CharPrefix" PREFIX_LENGTH="8" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
  <FIELD ID="5" xsi:type="CharPrefix" PREFIX_LENGTH="2" MAX_LENGTH="150" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="Id" xsi:type="SQLINT"/>
  <COLUMN SOURCE="2" NAME="Type" xsi:type="SQLSMALLINT"/>
  <COLUMN SOURCE="3" NAME="Language" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="4" NAME="Value" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="5" NAME="Subject" xsi:type="SQLVARYCHAR"/>
 </ROW>
</BCPFORMAT>

此 sql 脚本生成 sql 语句以从 bcp xml 格式文件创建表。

SET NOCOUNT ON
DECLARE @filePath NVARCHAR(256) = N'C:\table.xml'
      , @tableName SYSNAME = N'#myTable'
      , @xmlData XML
      , @sqlCmd NVARCHAR(1000)
      , @dmlQuery NVARCHAR(max) = N''
      , @crlf NVARCHAR(2) = CHAR(13)+ CHAR(10)
DECLARE @columns table(id INT NOT NULL, colName SYSNAME NOT NULL, dataType VARCHAR(50), [Length] INT NULL, [Precision] INT NULL, [Scale] INT NULL)
DECLARE @sql table(s VARCHAR(1000), id INT IDENTITY)

SET @sqlCmd = N'SET @xmlData = (
  SELECT * FROM OPENROWSET (
    BULK ''' + @filePath  + ''', SINGLE_BLOB
  ) AS xmlData
)';
EXEC sp_executesql @sqlCmd, N'@xmlData XML OUTPUT', @xmlData = @xmlData OUTPUT

;WITH XMLNAMESPACES 
(
    DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/bulkload/format',
            'http://www.w3.org/2001/XMLSchema-instance' as xsi
)
INSERT INTO @columns
SELECT  x.c.value('@SOURCE', 'INT'),
        x.c.value('@NAME', 'varchar(100)'),
        SUBSTRING(x.c.value('@xsi:type', 'varchar(100)'), 4, 20),
        ISNULL(y.f.value('@MAX_LENGTH', 'INT'), y.f.value('@LENGTH', 'INT')),
        x.c.value('@PRECISION', 'INT'),
        x.c.value('@SCALE', 'INT')
FROM @xmldata.nodes('/BCPFORMAT/ROW/COLUMN') x(c)
JOIN @xmldata.nodes('/BCPFORMAT/RECORD/FIELD') y(f) ON x.c.value('@SOURCE', 'INT') = y.f.value('@ID', 'INT')

UPDATE @columns SET dataType = REPLACE(dataType, 'VARYCHAR', 'VARCHAR');
UPDATE @columns SET dataType = REPLACE(dataType, 'DATETIM4', 'SMALLDATETIME');

INSERT INTO  @sql(s) VALUES ('create table ' + QUOTENAME(@tableName) + ' (')

INSERT INTO  @sql(s)
    SELECT @crlf 
        + QUOTENAME([colName])+ N' ' + [dataType] 
        + IIF([Length] IS NOT NULL AND [dataType] LIKE 'N%CHAR', '(' + CAST([Length]/2 AS VARCHAR) + ')', 
          IIF([Length] IS NOT NULL AND [dataType] LIKE '%CHAR', '(' + CAST([Length] AS VARCHAR) + ')', 
          IIF([Length] IS NULL AND [dataType] LIKE '%CHAR', '(MAX)', 
          IIF([Precision] IS NOT NULL AND [dataType] = 'DECIMAL', '(' + CAST([Precision] AS VARCHAR) + IIF([Scale] IS NOT NULL, ',' + CAST([Scale] AS VARCHAR), '') + ' )'
         , '') ) ) ) + ',' 
    FROM @columns
    ORDER BY id;


UPDATE @sql 
   SET s = left(s, len(s) - 1) 
 WHERE id = scope_identity()

INSERT INTO @sql(s) VALUES( ')' )

SELECT @dmlQuery += s 
  FROM @sql 
 ORDER BY id;

PRINT @dmlQuery -- sql query CREATE TABLE ….

然后就可以批量进入新创建的表了

BULK INSERT [#myTable] FROM 'C:\table.dat' WITH (KEEPIDENTITY, DATAFILETYPE='native', FORMATFILE = 'C:\table.xml');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多