如何根据 Sql 服务器中的 xml 在各个表中动态插入数据

How dynamically insert data in respective tables based upon xml in Sql server

我在存储过程中有这种类型的输入 XML 参数传递,它是从我的 .net 应用程序传递的。

现在,我需要在每个 table:

中插入记录
<root>
<table1>
<patid>123</patid>
<name>gresh</name>
<fname>kumar</name>
</table1>
<table2>
<patid>123</patid>
<Schoolname>12345</Schoolname>
</table2>
<tablen>
<patid>123</patid>
<nfield>12345</nfield>
</tablen>
<root>

假设table1将在table1中插入数据,table2中的数据在table2中,tablen意味着其他table的数量可能XML.

那么如何在每个 table 中插入?

您首先需要从XML获取数据。您的情况非常简单(我假设您只在一个 table 中插入数据一次,但是您可以轻松解决在一个 table 中多次插入的问题)。所以,下面的语句给了我:

SELECT T.c.value('local-name(.)','nvarchar(128)') AS tableName
      ,T1.c1.value('local-name(.)','nvarchar(128)') AS columName
      ,T1.c1.value('(./node())[1]','nvarchar(max)') AS value
FROM @XML.nodes('/root/*') T(c)
CROSS APPLY T.c.nodes('*') T1(c1)

然后,您需要对每个 table 的 insertion 的值进行分组(我正在使用 CLR 连接函数(您可以找到它 here,但是您也可以搜索 T-SQL 替代方案):

;WITH DataSource(tableName, columName, value)AS
(
    SELECT T.c.value('local-name(.)','nvarchar(128)')
          ,T1.c1.value('local-name(.)','nvarchar(128)')
          ,T1.c1.value('(./node())[1]','nvarchar(max)')
    FROM @XML.nodes('/root/*') T(c)
    CROSS APPLY T.c.nodes('*') T1(c1)
)
SELECT tableName
      ,[dbo].[Concatenate] (columName)
      ,[dbo].[Concatenate] (value)
FROM DataSource
GROUP BY tableName

您可以像这样进一步准备上述代码以进行动态执行:.

;WITH DataSource(tableName, columName, value)AS
(
    SELECT T.c.value('local-name(.)','nvarchar(128)')
          ,T1.c1.value('local-name(.)','nvarchar(128)')
          ,T1.c1.value('(./node())[1]','nvarchar(max)')
    FROM @XML.nodes('/root/*') T(c)
    CROSS APPLY T.c.nodes('*') T1(c1)
)
SELECT 'INSERT INTO ' + tableName  + '(' + [dbo].[Concatenate] (columName) + ') VALUES(' + [dbo].[Concatenate] ('''' + value + '''') + ');' 
FROM DataSource
GROUP BY tableName

现在,您只需构建一个 dynamic T-SQL string 并使用 sp_executesql 过程执行它:

DECLARE @XML XML = N'<root>
<table1>
<patid>123</patid>
<name>gresh</name>
<fname>kumar</fname>
</table1>
<table2>
<patid>123</patid>
<Schoolname>12345</Schoolname>
</table2>
<tablen>
<patid>123</patid>
<nfield>12345</nfield>
</tablen>
</root>';

DECLARE @DynamicSQLStatement NVARCHAR(MAX)

;WITH DataSource(tableName, columName, value)AS
(
    SELECT T.c.value('local-name(.)','nvarchar(128)')
          ,T1.c1.value('local-name(.)','nvarchar(128)')
          ,T1.c1.value('(./node())[1]','nvarchar(max)')
    FROM @XML.nodes('/root/*') T(c)
    CROSS APPLY T.c.nodes('*') T1(c1)
)
SELECT @DynamicSQLStatement =
(
    SELECT CHAR(10) + 'INSERT INTO ' + tableName  + '(' + [dbo].[Concatenate] (columName) + ') VALUES(' + [dbo].[Concatenate] ('''' + value + '''') + ');' 
    FROM DataSource
    GROUP BY tableName
    FOR XML PATH, TYPE
).value('.', 'NVARCHAR(MAX)')

PRINT @DynamicSQLStatement

EXEC sp_executesql @DynamicSQLStatement

请注意,我假设您的 XML 结构在数据库上下文中有效 - table 存在,列存在,并且列中插入的值是正确的。

如果需要,您可以添加更多检查。