Here is my trigger:
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
In the first lines of the script, I'm reading the DONORINFO
table in which I checked if the unique id exists. After that, I will insert the record into that table. I tested the first time, the insert into select script works but for the second time around, it fails and sends and a violation of primary key error.
But if I tested row by row insert, it works.
This is the row by row insert script that works.
INSERT INTO [dbo].[DONORINFO] ([DONORID], [DONORNAME])
VALUES ('DN00000001', 'test')
If I run it twice, the records will be like this:
DONORID DONORNAME
---------------------
DN00000001 test
DN00000002 test
This is the insert into select script that doesn't work:
INSERT INTO [dbo].[DONORINFO] ([DONORID], [DONORNAME])
SELECT
'',
[NameOfDonor]
FROM
[dbo].[_TEMPENDOWMENTFUND] AS ENDF
WHERE
[ENDF].[NameOfDonor] NOT IN (SELECT [DONORNAME]
FROM [dbo].[DONORINFO])
The _TEMPDOWMENTFUND
is a table I created that will store the data that was migrated from an Excel worksheet, the purpose of the trigger is that it will generate a unique DONORID
for every record inserted on the DONORINFO
table.
Now my problem is that, I want to perform the insert into select statement which is a multiple row insert, but I'm having a hard time figuring out what is going wrong to the trigger I created.
Any help would be appreciated. Thanks.
Make @sequence
totally int
(and probably rename it to last_id
), add characters in the very end.
To number rows use ROW_NUMBER()
in final select from 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
- is the length of DONORID
you need. I guess this may be a constant of 8 characters. In your source you are calculating this here:
SELECT @tranLen = LEN(@sequence)
t.rn
is a "sequence" value generated in subquery given above, which has t
alias. Renamed it to generated_id
for clarity.
This block:
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
is unnecessary anymore.
Here is the complete solution @ivan-starostin helped me answer.
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
So if I ran those two different insert into select
below...
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])
The donorid
iteration will be something like this with these two different table sources (I already omitted donor names because of confidentiality).
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.