您可以从XML创建表

时间:2015-11-10 19:16:46

标签: sql sql-server xml

这是一个理论问题,因为我此时没有用它。但是你可以从XML CREATE TABLE。例如,如果我运行

select    TABLE_CATALOG AS '@number', 
* from INFORMATION_SCHEMA.COLUMNS
order by 1
For XML Path ('root')

对于表

中的每种数据类型,我都得到这样的XML读数
<root number="testdb">
  <TABLE_CATALOG>testdb</TABLE_CATALOG>
  <TABLE_SCHEMA>dbo</TABLE_SCHEMA>
  <TABLE_NAME>tb_Population</TABLE_NAME>
  <COLUMN_NAME>ID</COLUMN_NAME>
  <ORDINAL_POSITION>1</ORDINAL_POSITION>
  <IS_NULLABLE>YES</IS_NULLABLE>
  <DATA_TYPE>varchar</DATA_TYPE>
  <CHARACTER_MAXIMUM_LENGTH>6</CHARACTER_MAXIMUM_LENGTH>
  <CHARACTER_OCTET_LENGTH>6</CHARACTER_OCTET_LENGTH>
  <CHARACTER_SET_NAME>iso_1</CHARACTER_SET_NAME>
  <COLLATION_NAME>SQL_Latin1_General_CP1_CS_AS</COLLATION_NAME>
</root>

我可以使用此xml并执行此类操作

    CREATE TABLE [dbo].[xmlTest] 
From declare @XML xml = 
    '<root number="testdb">
      <TABLE_CATALOG>testdb</TABLE_CATALOG>
      <TABLE_SCHEMA>dbo</TABLE_SCHEMA>
      <TABLE_NAME>tb_Population</TABLE_NAME>
      <COLUMN_NAME>ID</COLUMN_NAME>
      <ORDINAL_POSITION>1</ORDINAL_POSITION>
      <IS_NULLABLE>YES</IS_NULLABLE>
      <DATA_TYPE>varchar</DATA_TYPE>
      <CHARACTER_MAXIMUM_LENGTH>6</CHARACTER_MAXIMUM_LENGTH>
      <CHARACTER_OCTET_LENGTH>6</CHARACTER_OCTET_LENGTH>
      <CHARACTER_SET_NAME>iso_1</CHARACTER_SET_NAME>
      <COLLATION_NAME>SQL_Latin1_General_CP1_CS_AS</COLLATION_NAME>
    </root>'

显然这根本不正确,但你明白了。我只是想知道你是否可以对xml运行一个create table语句。如果你想从一个db重新创建表结构到另一个db,我可以看到这个被使用,但它们是不同的系统或类似的东西。或者也许我不知道我到底在说什么:-)

1 个答案:

答案 0 :(得分:2)

这个问题适合我重新发明轮子,因为您可以使用内置脚本编写器简单地生成表创建脚本。但出于学习原因,您可以解析XML并构建Dynamic-SQL

DECLARE @x XML =
N'<root number="testdb">
  <TABLE_CATALOG>testdb</TABLE_CATALOG>
  <TABLE_SCHEMA>dbo</TABLE_SCHEMA>
  <TABLE_NAME>tb_Population</TABLE_NAME>

  <COLUMN_NAME>ID</COLUMN_NAME>
  <ORDINAL_POSITION>1</ORDINAL_POSITION>
  <IS_NULLABLE>YES</IS_NULLABLE>
  <DATA_TYPE>varchar</DATA_TYPE>
  <CHARACTER_MAXIMUM_LENGTH>6</CHARACTER_MAXIMUM_LENGTH>
  <CHARACTER_OCTET_LENGTH>6</CHARACTER_OCTET_LENGTH>
  <CHARACTER_SET_NAME>iso_1</CHARACTER_SET_NAME>
  <COLLATION_NAME>SQL_Latin1_General_CP1_CS_AS</COLLATION_NAME>
</root>';

DECLARE @database SYSNAME,
        @schema SYSNAME,
        @table SYSNAME,
        @column_name SYSNAME,
        @column_position VARCHAR(100),
        @is_nullable VARCHAR(10),
        @data_type VARCHAR(100),
        @character_maximum VARCHAR(100),
        @collation_name VARCHAR(100);


SELECT 
@database = t.c.value('TABLE_CATALOG[1]', 'SYSNAME'),
@schema = t.c.value('TABLE_SCHEMA[1]', 'SYSNAME'),
@table = t.c.value('TABLE_NAME[1]', 'SYSNAME'),
@column_name = t.c.value('COLUMN_NAME[1]', 'VARCHAR(100)'),
@column_position = t.c.value('TABLE_NAME[1]', 'VARCHAR(100)'),
 @is_nullable = t.c.value('IS_NULLABLE[1]', 'VARCHAR(100)'),
@data_type = t.c.value('DATA_TYPE[1]', 'VARCHAR(100)'),
@character_maximum = t.c.value('CHARACTER_MAXIMUM_LENGTH[1]', 'VARCHAR(100)'),
@collation_name = t.c.value('COLLATION_NAME[1]', 'VARCHAR(100)')
FROM @x.nodes('/root') AS t(c);

DECLARE @sql NVARCHAR(MAX) = 
N' CREATE TABLE @database.@schema.@table(
      @column_name @data_type@character_maximum @is_nullable @collation_name
);';

SET @sql = REPLACE(@sql, '@database', QUOTENAME(@database));
SET @sql = REPLACE(@sql, '@schema', QUOTENAME(@schema));
SET @sql = REPLACE(@sql, '@table', QUOTENAME(@table));
SET @sql = REPLACE(@sql, '@column_name', QUOTENAME(@column_name));
SET @sql = REPLACE(@sql, '@data_type', QUOTENAME(@data_type));
SET @sql = REPLACE(@sql, '@character_maximum', 
                           CASE WHEN @character_maximum IS NULL THEN ''
                           ELSE CONCAT('(', @character_maximum, ')')
                           END);
SET @sql = REPLACE(@sql, '@is_nullable',
                           CASE WHEN @is_nullable = 'YES' THEN 'NULL'
                             ELSE 'NOT NULL'
                           END);

SET @sql = REPLACE(@sql, '@collation_name', 
                          CASE WHEN @collation_name IS NULL THEN ''
                           ELSE CONCAT('COLLATE ', @collation_name)
                           END);
PRINT @sql;

--EXEC [dbo].[sp_executesql]
--      @sql;

LiveDemo

输出:

CREATE TABLE [testdb].[dbo].[tb_Population](
      [ID] [varchar](6) NULL COLLATE SQL_Latin1_General_CP1_CS_AS
);

警告:

这不是生产代码,你不应该依赖它。仅用于演示目的。

当你走这条路时,你需要:

  • 处理角落案件
  • 检查您的XML未提供的许多内容(PRIMARY/FOREIGN KEY,约束,默认值)
  • 如果不检查每个参数,则会暴露于SQL注入攻击
  • 你需要遍历所有列,对于演示,我假设你只有一个
  • 根据类型更改代码
  • 更改XML结构以处理多个列
  • 越来越多

此任务是可行的,但使用SQL进行此操作会浪费时间,尤其是当您只需点击GENERATE SCRIPT时就可以了。