Как разделить переменные и значения, а затем вставить в таблицу? - PullRequest
0 голосов
/ 01 февраля 2019

Проблема

Хранимая процедура получает список переменных и значений, а также разделитель.Эта хранимая процедура должна вставить их в таблицу.

--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 или циклов.

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Вы всегда можете попробовать изменить данные.Это просто выборка, но в нее легко можно вставить вставку.

Мы используем разделенную строку с идентификатором строки, чтобы разрешить сопоставление двух разделенных наборов данных.Функция:

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, она хорошо документирована.

0 голосов
/ 01 февраля 2019

Если у вас всегда один и тот же набор имен столбцов, то это очень легко сделать с помощью поворота, но если столбцы меняются, вы можете использовать тот же сценарий с динамически настраиваемым списком переменных, предоставленным в качестве параметра или из прямого чтения извременная таблица:

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;
...