我的问题有点不寻常。
我有一个包含 3 列的表格 ( SQL Fiddle Link ):
ItemIdentifer ItemClasses RelevantItemDetails
Item1 Software <xml document>
Item1 CRM <xml document>
现在,我需要做的是:
选择具有给定标识符的行。 (比如 Item1)
为具有给定标识符的每一行构建一个临时表:这样 Table_Name 就是该行的 ItemClass。 (因此,在这种情况下,我将有 2 个表——软件和 CRM。)
将 RelevantItemDetails 值 => 一个 xml 文本 => 转换为相应表的表条目(我知道这个 :))。
我已经学会了通过 openxml 页面做第 3 步 https://learn.microsoft.com/en-us/sql/t-sql/functions/openxml-transact-sql .我创建了一个从 xml 返回表的 sql 过程。现在,我只需要将它插入到我在步骤 2 中创建的临时表中(同时包含列名和值)。我迷失了。
我怀疑对于 1 和 2,我必须构建一个动态执行这些操作的过程。
任何帮助都会非常有帮助。
澄清一下:我没有得到两件事:
以 ItemClass 名称作为表名动态构建表。 (所以,这里有 2 个表用于 Item1)。
该表的列和行由 xml 文档(即另一个表)定义。
So, I just need to create tables with name defined by ItemClass and columns and row entries defined by the xml document (assume I have a table created from the xml, it too will be dynamically generated, but I know how to generate it).
我在此处阅读了动态创建表 (T-SQL How to create tables dynamically in stored procedures?),但列是固定的。在我的例子中,列是从另一个表派生的。而且我也必须插入值(同样,从列所在的同一个表派生)。
编辑:示例行。
ID ItemName ItemClass Details
10 WebApp Software <root><row ID="10" ItemName="WebApp" ItemDescription="desc" DisplayID="4962" /></root>
编辑:最终表格示例。
TableName == Software
ID ItemName ItemDescription DisplayID
10 WebApp "desc" 4962
最佳答案
@items
表类似于您当前的表。然后是为每个 ItemClass
生成脚本的步骤。
DECLARE @n int, -- counter
@i int = 0, -- counter
@tableName nvarchar(255), -- stores name of the current table
@query nvarchar(4000) -- stores a query that creates table
-- creates table like yours
DECLARE @items TABLE (
ID int,
ItemName nvarchar(100),
ItemClass nvarchar(100),
Details xml
)
-- put some data in a table
INSERT INTO @items VALUES
(10, N'WebApp', N'Software', N'<root><row ID="10" ItemName="WebApp" ItemDescription="desc" DisplayID="4962" /></root>'),
(12, N'WebApp', N'Software', N'<root><row ID="12" ItemName="WebApp" ItemDescription="desc" DisplayID="5687" /></root>'),
(11, N'CRMapp', N'CRM', N'<root><row ID="11" ItemName="CRMapp" ItemDescription="desc" DisplayID="823678" /></root>')
-- that table will store data for script generating
DECLARE @tables TABLE (
ID int,
TableName nvarchar(100),
ColumnName sysname,
ColumnValue nvarchar(max)
)
--here we parse XML to get column names and data
INSERT INTO @tables
SELECT i.ID,
i.ItemClass as TableName,
CAST(t.c.query('local-name(.)') AS nvarchar(255)) AS ColumnName,
t.c.value('.', 'nvarchar(max)') ColumnValue
FROM @items i
CROSS APPLY Details.nodes('//@*') as t(c)
-- count tables
SELECT @n = COUNT(DISTINCT TableName)
FROM @tables
-- here we go!
WHILE @n > @i
BEGIN
-- select some table
SELECT TOP 1 @tableName = TableName
FROM @tables
-- in this CTE we get column names in order
;WITH tables_ AS (
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID ) as rn,
ColumnName
FROM @tables
WHERE TableName = @tableName
)
-- here we build the create part
SELECT @query = N'CREATE TABLE ' + QUOTENAME(@tableName) + '('
+
STUFF((
SELECT N','+ QUOTENAME(ColumnName) +' nvarchar(max)'
FROM tables_
GROUP BY rn,ColumnName
ORDER BY rn
FOR XML PATH('')),1,1,'')
+');
INSERT INTO ' + QUOTENAME(@tableName) +' VALUES'
-- here comes data
;WITH cte AS (
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID ) as rn,
ID,
ColumnValue
FROM @tables
WHERE TableName = @tableName
)
SELECT @query = @query + STUFF((
SELECT ',('''+ [1] + ''',''' +[2] + ''',''' +[3] + ''',''' +[4]+''')'
FROM cte
PIVOT (max (ColumnValue) for rn in ([1],[2],[3],[4])) as bb
FOR XML PATH('')),1,1,'');
-- print query
PRINT @query
---- execute query (first runt this script to print!)
--EXEC (@query)
SET @i+=1
SET @query = N''
DELETE FROM @tables
WHERE TableName = @tableName
END
这将生成(并执行)如下脚本:
CREATE TABLE [Software]([ID] nvarchar(max),[ItemName] nvarchar(max),[ItemDescription] nvarchar(max),[DisplayID] nvarchar(max));
INSERT INTO [Software] VALUES('10','WebApp','desc','4962'),('12','WebApp','desc','5687')
CREATE TABLE [CRM]([ID] nvarchar(max),[ItemName] nvarchar(max),[ItemDescription] nvarchar(max),[DisplayID] nvarchar(max));
INSERT INTO [CRM] VALUES('11','CRMapp','desc','823678')
您可以添加检查表是否已存在。以及一些为表列获取正确数据类型的逻辑。也许 XML 中可以有 4 个以上的属性。
关于SQL:从另一个表动态构建一个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46693420/