我在名为
AFTER INSERT
的表上有一个 FileInformation
触发器。
触发器在此表上执行两次更新。
单独插入
FileInformation
时工作正常。但是,当在与我的应用程序层中的另一个表的事务中将记录插入到此表中时,其中一个更新尝试从另一个表获取 Identity
值并用该值更新 FileInformation
表的插入记录value 不起作用,无法从插入事务内其他表的记录中获取标识值。
这就是我的触发器的样子:
ALTER TRIGGER [Infrastructure].[UpdateFileInformationAfterInsert]
ON [Infrastructure].[FileInformation]
AFTER INSERT
AS
BEGIN
DECLARE @InsertedCode AS int;
DECLARE @SQLQuery AS nvarchar(MAX);
DECLARE @DataBaseTableName AS nvarchar(100);
DECLARE @DataBaseTableRowID AS uniqueidentifier;
DECLARE @ProjectComponentID AS uniqueidentifier;
DECLARE @BoundedContext AS nvarchar(200);
DECLARE @Code AS int;
SELECT
@InsertedCode = Code,
@DataBaseTableName = DataBaseTableName,
@DataBaseTableRowID = DataBaseTableRowID,
@ProjectComponentID = ProjectComponentID
FROM
inserted
SET @BoundedContext = (SELECT Name
FROM [Infrastructure].[BoundedContext]
WHERE ID = (SELECT BoundedContextID
FROM [Infrastructure].[ProjectComponent]
WHERE ID = @ProjectComponentID))
SET @SQLQuery = CONCAT('select @Code=Code from [', @BoundedContext ,'].[',@DataBaseTableName,'] where ID=''',@DataBaseTableRowID,'''')
EXEC sp_executesql @SQLQuery ,N'@Code int output',@Code=@Code output
UPDATE [Infrastructure].[FileInformation]
SET DataBaseTableRowCode = @Code
WHERE Code = @InsertedCode
IF (SELECT Value FROM [Infrastructure].[ConfigurationSetting]
WHERE Name = N'FileSavingMethod') = N'0'
BEGIN
DECLARE @FileSavingRootPath AS nvarchar(MAX)
SET @FileSavingRootPath = (SELECT Value
FROM [Infrastructure].[ConfigurationSetting]
WHERE Name = N'FileSavingRootPath')
UPDATE [Infrastructure].[FileInformation]
SET FileSavePath = CONCAT('~\', @FileSavingRootPath, '\', [Infrastructure].[GetSubDirectory] (@InsertedCode))
WHERE Code = @InsertedCode
END
END
正如我提到的,上面代码中的第一个
UPDATE
在执行与另一个表的事务时不起作用。
我的问题:我读过一些关于
SCOPE_IDENTITY
、@@IDENTITY
、IDENT_CURRENT
的答案。是否可以从另一个表获取身份值(通过使用其名称,如 IDENT_CURRENT('tablename')
),在我的代码中是 @DataBaseTableName
BUT 在当前范围和会话内?
不应考虑 IDENT_CURRENT。用于并发活动是不安全的。
无法使用 IDENT_CURRENT('tablename') 等名称从其他表获取标识值。使用 SQL Server 2016,您可以考虑使用 sp_set_session_context 来设置仅在会话范围内的变量。