On a SQL Server 2008 R2 database server, I attempt to insert data into a table, but the INSERT statement's OUTPUT clause returns only zeros for the table's Identity column. The INSERT statement below is part of a larger script with many statements wrapped in a single transaction.
Here is the statement:
INSERT INTO CountryDivisions (
[CountryID]
, [ParentDivisionID]
, [DivisionCodeISO]
, [DivisionCodeShort]
, [DivisionType]
)
OUTPUT
inserted.[CountryDivisionID] -- Identity column, returning only zeros!
, inserted.[CountryID]
, inserted.[ParentDivisionID]
, inserted.[DivisionCodeISO]
, inserted.[DivisionCodeShort]
, inserted.[DivisionType]
INTO @NewCountryDivisions
SELECT
dc.[CountryID]
, null
, COALESCE(mcd.DependentDivisionCodeISO, mcd.ParentCountryAlpha2Code + '-' + mcd.DependentCountryAlpha2Code)
, mcd.DependentCountryAlpha2Code
, mcd.DependentDivisionType
FROM
@MoreCountryData AS mcd
JOIN Countries AS dc
ON dc.Alpha2Code = mcd.DependentCountryAlpha2Code
WHERE
NOT EXISTS (
SELECT *
FROM CountryDivisions AS cd2
WHERE
cd2.[CountryID] = dc.[CountryID]
AND cd2.[DivisionCodeShort] = mcd.DependentCountryAlpha2Code
)
This is what I see when selecting from @NewCountryDivisions:

Here is the table's definition:
CREATE TABLE [dbo].[CountryDivisions](
[CountryDivisionID] [int] IDENTITY(1,1) NOT NULL, -- identity column which is only returning zeros!
[CountryID] [int] NOT NULL,
[ParentDivisionID] [int] NULL,
[DivisionCodeISO] [nvarchar](10) NULL,
[DivisionCodeShort] [nvarchar](10) NULL,
[DivisionType] [nvarchar](150) NULL,
[LastUpdatedBy] [sysname] NOT NULL DEFAULT (user_name()),
[LastUpdatedDateTime] [datetime] NOT NULL DEFAULT (getutcdate()),
CONSTRAINT [PK_CountryDivisions_CountryDivisionID] PRIMARY KEY NONCLUSTERED
(
[CountryDivisionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
I am using INSTEAD OF triggers to update the two LastUpdated... columns. I am new to writing triggers, though I would not expect these to cause the problem, but just in case, here are their definitions:
CREATE TRIGGER [dbo].[CountryDivisions_InsertAudit]
ON [dbo].[CountryDivisions]
INSTEAD OF INSERT
AS
BEGIN
SET NoCount ON
INSERT INTO [dbo].[CountryDivisions] (
-- I am assuming that SQL Server will apply the IDENTITY process to the [CountryDivisionID] column, so I am not inserting it myself.
[CountryID]
, [ParentDivisionID]
, [DivisionCodeISO]
, [DivisionCodeShort]
, [DivisionType]
, [LastUpdatedBy]
, [LastUpdatedDateTime]
)
SELECT
i.CountryID
, i.ParentDivisionID
, i.DivisionCodeISO
, i.DivisionCodeShort
, i.DivisionType
, COALESCE(NULLIF(LTRIM(RTRIM(i.[LastUpdatedBy])), ''), USER_NAME())
, COALESCE(i.[LastUpdatedDateTime], GETUTCDATE())
FROM
inserted AS i
END
CREATE TRIGGER [dbo].[CountryDivisions_UpdatAudit]
ON [dbo].[CountryDivisions]
INSTEAD OF UPDATE
AS
BEGIN
SET NoCount ON
UPDATE [dbo].[CountryDivisions]
SET
CountryID = i.CountryID
, ParentDivisionID = i.ParentDivisionID
, DivisionCodeISO = i.DivisionCodeISO
, DivisionCodeShort = i.DivisionCodeShort
, DivisionType = i.DivisionType
, LastUpdatedBy = COALESCE(NULLIF(LTRIM(RTRIM(i.[LastUpdatedBy])), ''), USER_NAME())
, LastUpdatedDateTime = COALESCE(i.[LastUpdatedDateTime], GETUTCDATE())
FROM
[dbo].[CountryDivisions] AS cd
JOIN inserted AS i
JOIN deleted AS d
ON d.CountryDivisionID = i.CountryDivisionID
ON cd.CountryDivisionID = i.CountryDivisionID
WHERE
-- only update records that have actually been updated.
i.CountryID <> d.CountryID
OR ISNULL(i.ParentDivisionID, -1) <> ISNULL(d.ParentDivisionID, -1)
OR ISNULL(i.DivisionCodeISO, '') <> ISNULL(d.DivisionCodeISO, '')
OR ISNULL(i.DivisionCodeShort, '') <> ISNULL(d.DivisionCodeShort, '')
OR (
ISNULL(i.LastUpdatedBy, '') <> ISNULL(d.LastUpdatedBy, '')
AND UPDATE(LastUpdatedBy)
)
OR (
ISNULL(i.LastUpdatedDateTime, '1900-01-01') <> ISNULL(d.LastUpdatedDateTime, '1900-01-01')
AND UPDATE(LastUpdatedDateTime)
)
END
It seems that my triggers were the problem!
From a comment someone made in another Stack Overflow thread,
OUTPUTclauses onINSERTstatements where the underlying table contains anINSTEAD OFtrigger will return only zeros for any column defined with theIDENTITY(seed, increment)function.To get around this problem I rewrote my triggers as
AFTERan trigger. This also let me consolidate two triggers into one trigger.