我有一个带有IDENTITY
列的表,并且在此表上有一个INSTEAD OF
触发器。如果打开了IDENTITY_INSERT
,我想插入为IDENTITY
列手动指定的值。
有什么办法可以适当地应对这种情况,例如检测IDENTITY_INSERT
的值?从读取结果来看,过去似乎无法检测到特定表的IDENTITY_INSERT
当前值。我不知道新版本的SQL Server是否可行。
表创建SQL:
CREATE TABLE [TestTable]
(
[Id] INTEGER IDENTITY NOT NULL PRIMARY KEY,
[ExampleField] BIT NOT NULL DEFAULT(1)
)
这是我目前正在尝试的方法,但是似乎很浪费,因为
IDENTITY_INSERT
可能在大多数时间都处于关闭状态,这意味着它在第一次插入尝试时总是会失败,这在性能上是浪费的。 。CREATE TRIGGER [dbo].[trTestTable_ioi] ON [dbo].[TestTable] INSTEAD OF INSERT
AS
BEGIN
BEGIN TRY
INSERT INTO [TestTable]([Id],[ExampleField])
SELECT [Id], [ExampleField]
FROM [inserted]
END TRY
BEGIN CATCH
INSERT INTO [TestTable]([ExampleField])
SELECT [ExampleField]
FROM [inserted]
END CATCH
END
最佳答案
如果IDENTITY
种子和增量使得生成的值始终为非零(正种子和增量或负种子和增量),则可以在虚拟inserted
表中检查非零值,并使用该值存在时的价值。这取决于我的观察,使用INSTEAD OF
触发器和IDENTITY_INSERT OFF
,标识值为零。但是,我找不到这种行为的专门记录,因此您应该在自己的环境中进行审核,并自行承担风险。
例:
CREATE TRIGGER [dbo].[trTestTable_ioi] ON [dbo].[TestTable] INSTEAD OF INSERT
AS
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM inserted WHERE ID <> 0)
BEGIN
--IDENTITY_INSERT is ON
INSERT INTO [TestTable]([Id],[ExampleField])
SELECT [Id], [ExampleField]
FROM [inserted];
END
ELSE
BEGIN
--IDENTITY_INSERT is OFF
INSERT INTO [TestTable]([ExampleField])
SELECT [ExampleField]
FROM [inserted];
END;
GO
SET IDENTITY_INSERT dbo.TestTable OFF;
GO
--identity value auto-assigned
INSERT INTO TestTable VALUES(1);
GO
SET IDENTITY_INSERT dbo.TestTable ON;
GO
--explict identity value specified
INSERT INTO TestTable(ID, ExampleField) VALUES(11, 1);
GO
SET IDENTITY_INSERT dbo.TestTable OFF;
GO
--fails as expected because identity value cannot be specified with IDENTITY_INSERT OFF
INSERT INTO TestTable(ID, ExampleField) VALUES(11, 1);
GO
SET IDENTITY_INSERT dbo.TestTable ON;
GO
--fails as expected because identity value must be specified with IDENTITY_INSERT ON
INSERT INTO TestTable VALUES(1);
GO