问题
存储过程正在接收变量和值以及定界符的列表。此存储过程需要将它们插入表中。
--Example table
create table #tempo
(
Variable1 int,
Variable2 int,
Variable3 int
)
这些是存储过程的参数:
declare @variableList varchar(100)
declare @valueList varchar(100)
declare @separator char(1)
set @variableList = 'Variable1#Variable2#Variable3'
set @valueList = '1111#2222#3333'
set @separator = '#'
结果
我想实现的是这样:
select * from #tempo
+---------+---------+---------+
|Variable1|Variable2|Variable3|
+---------+---------+---------+
|1111 |2222 |3333 |
+---------+---------+---------+
一种实现方式
我可以使用循环并构建动态SQL,但我想避免这种情况。除了不使用动态SQL的明显原因外,循环结构难以维护,解释和测试也可能成为问题。
理想方式
我想一个更优雅的方式来做到这一点,例如使用string_split或coalesce等,但不能想出一个办法,而不使用动态SQL或循环。
答案 0 :(得分:1)
如果您始终具有相同的列名集,则很容易进行透视操作,但是如果列正在更改,则可以使用具有动态调整的变量列表的同一脚本(作为参数或直接从中读取)临时表:
INSERT INTO #tempo SELECT *
FROM (
SELECT [value], rv = 'Variable' + CAST(Row_Number() OVER ( ORDER BY (SELECT 1)) as VARCHAR)
FROM STRING_SPLIT(@valueList,@separator)
) AS src
PIVOT (MAX([value]) FOR rv IN (Variable1,Variable2,Variable3)) AS pvt;
答案 1 :(得分:1)
您始终可以尝试透视数据。这只是选择,但可以很容易地将插入物包裹在其中。
我们使用具有行ID的拆分字符串来允许两个拆分数据集的匹配。功能是:
CREATE FUNCTION [dbo].[Split] (@RowData NVARCHAR(MAX), @SplitOn NVARCHAR(5))
RETURNS @RtnValue TABLE (Id INT IDENTITY(1, 1), Data NVARCHAR(100))
AS
BEGIN
DECLARE @Cnt INT;
SET @Cnt = 1;
WHILE (CHARINDEX(@SplitOn, @RowData) > 0)
BEGIN
INSERT INTO @RtnValue (Data)
SELECT Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, CHARINDEX(@SplitOn, @RowData) - 1)));
SET @RowData = SUBSTRING(@RowData, CHARINDEX(@SplitOn, @RowData) + 1, LEN(@RowData));
SET @Cnt = @Cnt + 1;
END;
INSERT INTO @RtnValue (Data)
SELECT Data = LTRIM(RTRIM(@RowData));
RETURN;
END;
然后,您可以将这两个集合结合在一起以提供一些键值对,然后从中透视出数据以提供所需的格式。如果将最后一个选择替换为先前任何一个CTE的选择,那么您将了解逻辑的展开方式。
DECLARE @variableList VARCHAR(100);
DECLARE @valueList VARCHAR(100);
DECLARE @separator CHAR(1);
SET @variableList = 'Variable1,Variable2,Variable3';
SET @valueList = '1111, 2222, 3333';
SET @separator = ',';
WITH cteVar AS (SELECT Id, Data FROM dbo.Split(@variableList, @separator) )
, cteVal AS (SELECT Id, Data FROM dbo.Split(@valueList, @separator) )
, cteData AS
(SELECT cteVar.Data VariableData
, cteVal.Data ValueData
FROM cteVar
JOIN cteVal ON cteVal.Id = cteVar.Id)
, ctePivot AS
(SELECT *
FROM cteData
PIVOT ( MAX(ValueData)
FOR VariableData IN ([Variable1], [Variable2], [Variable3])) AS PivotTable)
SELECT *
FROM ctePivot;
这是一个很长的解决方法,但希望它能很好地帮助您理解所涉及的步骤。无论如何,值得一看的是Pivot函数,它有据可查。