ВСТАВИТЬ, используя T- SQL с 2 табличными функциями - PullRequest
1 голос
/ 10 февраля 2020

У меня есть хранимая процедура, которая принимает два параметра NVARCHAR, которые принимают список значений имен и индексов, разделенных запятыми, и вставляют их в таблицу базы данных сервера SQL в одну go.

CREATE PROCEDURE [dbo].[SplitAndSave]   
    @name nvarchar(MAX),
    @vals nvarchar(MAX)

Данные будут иметь формат, в котором каждый из идентификаторов @name совпадает в той же последовательности, что и @vals:

@name = 1,2,3,4
@vals = 9,8,7,6

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

CREATE FUNCTION [dbo].[fnSplitString] ( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 

DECLARE @start INT, @end INT 
SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 

WHILE @start < LEN(@string) + 1 BEGIN 
    IF @end = 0  
        SET @end = LEN(@string) + 1

    INSERT INTO @output (splitdata)  
    VALUES(SUBSTRING(@string, @start, @end - @start)) 
    SET @start = @end + 1 
    SET @end = CHARINDEX(@delimiter, @string, @start)

END 

RETURN 

END

В своей хранимой процедуре я пытаюсь «объединить» две табличные функции:

INSERT INTO KEY_DATA (name, value)
(SELECT splitdata from fnSplitString(@name, ',')), (SELECT splitdata from fnSplitString(@value, ','))

Но я получаю ошибка:

Сообщение 512, уровень 16, состояние 1, процедура dbo.SplitAndSave, строка 17 [Строка пакетного запуска 2]
Подзапрос вернул более 1 значения. Это недопустимо, когда подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения.

Я думаю, что мне может понадобиться обернуть первый стол во второй, но я не думаю, что это можно сделать «все в одном» go.

Есть мысли, как мне этого добиться? В настоящее время используется SQL Server Management Studio v17.8

1 Ответ

3 голосов
/ 10 февраля 2020

Проблема не в функции, а в том, как вы вставляете данные. Следующий код:

INSERT INTO KEY_DATA (name, value)
(SELECT splitdata from fnSplitString(@name, ',')), (SELECT splitdata from fnSplitString(@value, ','))

за исключением:

INSERT INTO KEY_DATA (name, value)
(one value of name), (one value of value)

, но в ваших утверждениях возвращаются более одного значения. Вот в чем проблема.

Вам необходимо добавить индекс порядка в вашу функцию и присоединиться к ней. Примерно так:

INSERT INTO KEY_DATA (name, value)
SELECT DS1.splitdata 
      ,DS2.splitdata
from fnSplitString(@name, ',') DS1
INNER JOIN fnSplitString(@value, ',') DS2
    ON DS1.[OrderIndex] = DS2.[OrderINdex];

Например:

CREATE OR ALTER FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE
(
    [orderID] BIGINT
   ,[splitdata] NVARCHAR(MAX)
) 
BEGIN 

    DECLARE @XML XML = CAST(N'<r><![CDATA[' + REPLACE(@string, @delimiter, ']]></r><r><![CDATA[') + ']]></r>' AS XML)

    INSERT INTO @output ([orderID], splitdata)
    SELECT  ROW_NUMBER() OVER(ORDER BY T.c)
           ,RTRIM(LTRIM(T.c.value('.', 'nvarchar(MAX)')))
    FROM @XML.nodes('//r') T(c)

    RETURN 

END 
GO


DECLARE @name NVARCHAR(MAX) = '1,2,3,4'
       ,@vals NVARCHAR(MAX) = '9,8,7,6'


SELECT DS1.[splitdata] 
      ,DS2.[splitdata]
from dbo.fnSplitString(@name, ',') DS1
INNER JOIN dbo.fnSplitString(@vals, ',') DS2
    ON DS1.[orderID] = DS2.[orderID];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...