0

Вот мой триггер:Невозможно выполнить несколько строк вставки на триггер при вставке записи с уникальным идентификатором

ALTER TRIGGER DONORINFO_INSERT 
ON [dbo].[DONORINFO] INSTEAD OF INSERT 
AS 
    DECLARE @sequence AS VARCHAR(50) = '' 
    DECLARE @tranLen VARCHAR(10) 

    SET @sequence = (SELECT TOP 1 SUBSTRING([DONORID], 3, 8) 
        FROM [dbo].[DONORINFO] 
        ORDER BY [DONORID] DESC) 

    IF (@sequence IS NULL OR @sequence = '') 
    BEGIN   
     SELECT @sequence = REPLICATE('0', 7) + '1'     
    END 
    ELSE    
    BEGIN   
     SELECT @tranLen = LEN(@sequence) 
     SELECT @sequence = @sequence + 1  
     SELECT @tranLen = ABS(@tranLen - LEN(CAST(@sequence AS INT))) 
     SELECT @sequence = REPLICATE('0', @tranLen) + @sequence 
    END  

    DECLARE @DONORID AS [nvarchar](50) = 'DN' + CONVERT(VARCHAR, @sequence) 

    INSERT INTO [dbo].[DONORINFO] ([DONORID], [DONORNAME]) 
     SELECT @DONORID, inserted.DONORNAME 
     FROM inserted 

В первых строках сценария, я читал таблицу DONORINFO, в котором я проверил, если существует уникальный идентификатор. После этого я вставлю запись в эту таблицу. Я протестировал первый раз, вставка в скрипт работает, но во второй раз он терпит неудачу и отправляет и нарушает ошибку первичного ключа.

Но если я проверил строку за строкой, она работает.

Это скрипт вставки строки за строкой, который работает.

INSERT INTO [dbo].[DONORINFO] ([DONORID], [DONORNAME]) 
VALUES ('DN00000001', 'test') 

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

DONORID  DONORNAME 
--------------------- 
DN00000001 test  
DN00000002 test  

Это вставка в выберите сценарий, который не работает:

INSERT INTO [dbo].[DONORINFO] ([DONORID], [DONORNAME]) 
    SELECT 
     '', 
     [NameOfDonor] 
    FROM 
     [dbo].[_TEMPENDOWMENTFUND] AS ENDF 
    WHERE 
     [ENDF].[NameOfDonor] NOT IN (SELECT [DONORNAME] 
            FROM [dbo].[DONORINFO]) 

_TEMPDOWMENTFUND является созданная таблица, в которой будут храниться данные, перенесенные с листа Excel, целью триггера является то, что он будет генерировать уникальный DONORID для каждой записи, вставленной на t он DONORINFO таблица.

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

Любая помощь будет оценена по достоинству. Благодарю.

ответ

0

Сделайте @sequence полностью int (и, вероятно, переименуйте его в last_id), добавьте персонажей в самом конце.

Для нумерации строк используйте ROW_NUMBER() в финале выбрать из INSERTED:

INSERT INTO [dbo].[DONORINFO] ([DONORID], [DONORNAME]) 
SELECT 
    'DN' + REPLICATE('0', ABS(@len_you_need - LEN(t.generated_id))) + CAST (t.generated_id as varchar(100)), 
    t.DONORNAME 
FROM 
(
SELECT 
    i.DONORNAME, 
    @sequence+ROW_NUMBER()OVER(ORDER BY i.DONORNAME) as generated_id 
FROM inserted i 
) t 

@len_you_need - длина DONORID вам нужно. Я предполагаю, что это может быть константа в 8 символов. В вашем источнике вы вычисляете это здесь:

SELECT @tranLen = LEN(@sequence) 

t.rn является «последовательность» значением, генерируемым в подзапросе приведенного выше, который имеет t псевдоним. Для ясности переименовали его в generated_id.

Этот блок:

BEGIN   
    SELECT @tranLen = LEN(@sequence) 
    SELECT @sequence = @sequence + 1 
    SELECT @tranLen = ABS(@tranLen - LEN(CAST(@sequence AS INT))) 
    SELECT @sequence = REPLICATE('0', @tranLen) + @sequence 
END 

ненужно больше.

+0

Привет, я не могу заставить его работать, можете ли вы опубликовать весь сценарий, чтобы затем проверить его? – japogs

+0

@ japogs007ph нет, вы должны приложить некоторые усилия самостоятельно. «Весь скрипт» - это ваш скрипт запуска. Если вы _ «не можете заставить его работать» _ - обновите свой вопрос с помощью текущей проблемы и текущего кода. Начните с заголовка '# UPD Code с ROWNUMBER' –

+0

Я уже пробовал часть вашего скрипта, но я не понимаю, где получить значение' @ len_tou_need' и 't.rn'. Я немного новичок в создании триггера, и я прошу прощения за это. Я уже пробовал свои усилия, чтобы исследовать этот вопрос, поэтому я спрашиваю его здесь. – japogs

0

Вот полное решение @ ivan-starostin помогло мне ответить.

ALTER TRIGGER DONORINFO_INSERT ON [dbo].[DONORINFO] 
INSTEAD OF INSERT, UPDATE 
AS 
DECLARE @sequence AS VARCHAR(50) = '' 
DECLARE @tranLen VARCHAR(10) 

SET @sequence = (SELECT TOP 1 SUBSTRING([DONORID], 3, 8) FROM [dbo].[DONORINFO] ORDER BY [DONORID] DESC) 

IF (@sequence IS NULL OR @sequence = '') 
BEGIN   
    SELECT @sequence = REPLICATE('0', 7) 
END 
ELSE    
BEGIN   
    SELECT @tranLen = LEN(@sequence) 
    SELECT @sequence = @sequence + 1 
    SELECT @tranLen = ABS(@tranLen - LEN(CAST(@sequence AS INT))) 
    SELECT @sequence = REPLICATE('0', @tranLen) + @sequence 
END  


INSERT INTO [dbo].[DONORINFO] ([DONORID], [DONORNAME]) 
SELECT 
    'DN' + REPLICATE('0', ABS(8 - LEN(t.generated_id))) + CAST (t.generated_id  as varchar(100)), 
    t.DONORNAME 
FROM 
(
SELECT 
    i.DONORNAME, 
    @sequence+ROW_NUMBER()OVER(ORDER BY i.DONORNAME) as generated_id 
FROM inserted i 
) t 

Так что если бы я запустил эти два разных insert into select ниже ...

INSERT INTO [dbo].[DONORINFO] ([DONORNAME]) 
SELECT 
[NameOfDonor] 
FROM [dbo].[_TEMPENDOWMENTFUND] AS ENDF 
WHERE [ENDF].[NameOfDonor] NOT IN (SELECT [DONORNAME] FROM [dbo].[DONORINFO]) 

INSERT INTO [dbo].[DONORINFO] ([DONORNAME]) 
SELECT 
[NameOfDonor] 
FROM [dbo].[_TEMPENDOWED] AS ENDF 
WHERE [ENDF].[NameOfDonor] NOT IN (SELECT [DONORNAME] FROM [dbo].[DONORINFO]) 

donorid итерация будет что-то подобное с этих двух разных источников таблицы (я уже опущена имена доноров, из-за конфиденциальности).

DONORID DONORNAME (from _TEMPENDOWMENTFUND) 
------------------------ 
DN00000001 test 
DN00000002 test 
DN00000003 test 
DN00000004 test 
DN00000005 test 
DN00000006 test 
DN00000007 test 

DONORID DONORNAME (from _TEMPENDOWED) 
------------------------ 
DN00000007 test 
DN00000008 test 
DN00000009 test 
DN00000010 test 
DN00000011 test 
DN00000012 test 
DN00000013 test 
Смежные вопросы