Другой возможный подход - преобразовать ваши текстовые данные в действительные массивы JSON
, а затем использовать OPENJSON () с явной схемой и динамическим оператором.
Рабочий пример:
Ввод:
CREATE TABLE #Data (
RowNum int,
Line nvarchar(max)
)
INSERT INTO #Data
(RowNum, Line)
VALUES
(1, 'ColumnA;ColumnB;ColumnC'),
(2, 'ValueA1;ValueB1;ValueC1'),
(3, 'ValueA2;ValueB2;ValueC2'),
(4, 'ValueA3;ValueB3;ValueC3'),
(5, 'ValueA4;ValueB4;ValueC4'),
(6, 'ValueA5;ValueB5;ValueC5')
T-SQL:
-- Explicit schema generation
DECLARE @schema nvarchar(max)
SELECT @schema = STUFF((
SELECT CONCAT(N',', j.[value], N' nvarchar(max) ''$[', j.[key], N']''')
FROM #Data d
CROSS APPLY OPENJSON(CONCAT(N'["', REPLACE(d.Line, ';', '","'), N'"]')) j
WHERE d.RowNum = 1
FOR XML PATH('')
), 1, 1, N'')
-- Dymanic statement
DECLARE @stm nvarchar(max)
SET @stm = CONCAT(
N'SELECT j.* FROM #Data d ',
N'CROSS APPLY OPENJSON(CONCAT(N''[["'', REPLACE(d.Line, '';'', ''","''), N''"]]'')) ',
N'WITH (',
@schema,
N') j WHERE d.RowNum > 1'
)
-- Execution
EXEC sp_executesql @stm
Ввод:
-----------------------
ColumnA ColumnB ColumnC
-----------------------
ValueA1 ValueB1 ValueC1
ValueA2 ValueB2 ValueC2
ValueA3 ValueB3 ValueC3
ValueA4 ValueB4 ValueC4
ValueA5 ValueB5 ValueC5
Пояснения:
Основная часть заключается в преобразовании данных каждой строки в действительные массивы JSON
.Количество столбцов может быть различным.
Данные из первой строки будут использоваться для явного создания схемы, а значения ColumnA;ColumnB;ColumnC
преобразуются в ["ColumnA","ColumnB","ColumnC"]
.Значения из последующих строк ValueA1;ValueB1;ValueC1
преобразуются в [["ValueA1","ValueB1","ValueC1"]]
.
Следующие простые примеры демонстрируют, как OPENJSON()
возвращает данные со стандартной и явной схемой:
Со стандартной схемой:
DECLARE @json nvarchar(max)
SET @json = '["ValueA1", "ValueB1", "ValueC1"]'
SELECT *
FROM OPENJSON(@json)
Вывод для схемы по умолчанию:
----------------
key value type
----------------
0 ValueA1 1
1 ValueB1 1
2 ValueC1 1
С явной схемой:
SET @json = '[["ValueA1", "ValueB1", "ValueC1"]]'
SELECT *
FROM OPENJSON(@json)
WITH (
ColumnA nvarchar(max) '$[0]',
ColumnB nvarchar(max) '$[1]',
ColumnC nvarchar(max) '$[2]'
)
Вывод для явной схемы:
-----------------------
ColumnA ColumnB ColumnC
-----------------------
ValueA1 ValueB1 ValueC1