我们的其他用户的源表每次都有不同的列数。例如,今天的表格如下:
Name Eye tail
-------------------
Dog Blue long
Cat Red short
但明天是:
Name eye tail skin
-------------------
Dog blue long white
Lion green short brown
我们的目标是将数据传输到这样一个固定的模式表中:
name property value
-------------------------
Dog Eye blue
Dog tail long
Dog skin white
Lion Eye green
Lion Tail short
Lion skin brown
为实现这一目标,现在我们使用半手动修改的存储过程进行此类转换:
SELECT *
INTO #T
FROM table.original
INSERT INTO table.target(name, property, value)
SELECT name, property, value
FROM
--below is manually modified each time
(SELECT name = a.name, property = 'eye', value = a.eye
FROM #T a
UNION ALL
SELECT name, 'tail', tail
FROM #T
UNION ALL
SELECT name, 'skin', skin
FROM #T
UNION ALL
.........
)
有没有办法自动进行此类转换?我认为FOR XML
可以解决这个问题,但是如何解决?
答案 0 :(得分:2)
看起来非常适合动态UNPIVOT
:
DECLARE @columns NVARCHAR(MAX);
SELECT @columns = STUFF ((SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [table_name] = 'tab'
AND column_name <> 'Name'
FOR XML PATH ('')),1,1,'');
DECLARE @sql NVARCHAR(MAX) =
N'INSERT INTO target(name, property, [value])
SELECT Name, property, [value]
FROM tab t
UNPIVOT
(
[value] FOR property IN (<placeholder>)
) unpvt;';
SET @sql = REPLACE(@sql, '<placeholder>', @columns);
EXEC dbo.sp_executesql
@sql;
SELECT *
FROM target;
输出:
╔═══════╦═══════════╦═══════╗
║ name ║ property ║ value ║
╠═══════╬═══════════╬═══════╣
║ Dog ║ eye ║ blue ║
║ Dog ║ tail ║ long ║
║ Dog ║ skin ║ white ║
║ Lion ║ eye ║ green ║
║ Lion ║ tail ║ short ║
║ Lion ║ skin ║ brown ║
╚═══════╩═══════════╩═══════╝
工作原理:
从输入表的元数据中获取列列表并将它们连接起来[eye],[tail],[skin]
使用占位符为列
将占位符替换为实际列名
执行dynamic-SQL
检查EAV
表