This question has been asked before...but I can't seem to find the exact answer I'm looking for... I need to insert a bunch of records and get back the inserted identity values... I'm doing this:
INSERT MyTable(col1, ....)
OUTPUT inserted.IdentityColumn
SELECT p.i.value('@XmlAttribute', 'nvarchar(128)') FROM @myXml.nodes('/root/i') AS p(i)
This works fine...
Enter SQL transactional replication with updatable subscriptions, which places triggers on replicated tables on subscribers.
OUTPUT no longer works in this scenario...
So, I'm doing this now...but I have a bad feeling in my gut about this and I think I've opened the door to a concurrency issue (though I'm not positive).
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
DECLARE @currentIdentity bigint
SET @currentIdentity = SELECT IDENT_CURRENT('MyTable') + 1
...
SELECT IdentityColumn FROM MyTable WHERE IdentityColumn <= IDENT_CURRENT('MyTable') AND IdentityColumn >= @currentIdentity
Suggestions? This also stinks because the approach doesn't work for generated uniqueidentifiers.
You can use the variant of OUTPUT that inserts into a table variable. From the documentation:
If the OUTPUT clause is specified without also specifying the INTO keyword, the target of the DML operation cannot have any enabled trigger defined on it for the given DML action. For example, if the OUTPUT clause is defined in an UPDATE statement, the target table cannot have any enabled UPDATE triggers.
(Emphasis added)
So, you can have:
DECLARE @IDs table (ID int not null)
INSERT MyTable(col1, ....)
OUTPUT inserted.IdentityColumn INTO @IDs
SELECT p.i.value('@XmlAttribute', 'nvarchar(128)') FROM @myXml.nodes('/root/i') AS p(i)
SELECT * from @IDs
Which will have approximately the same behaviour as the original, unless you're processing e.g. row count messages.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With