mim*_*imo 0 sql t-sql sql-server triggers calculated-columns
请考虑下表。我使用触发器添加到表中。在将数字转换为字符串的列中,它失败。
CREATE TABLE [dbo].[tblAIAgent]
(
[AgentCode] [NVARCHAR](10) NOT NULL,
[NationalCode] [BIGINT] NOT NULL
CONSTRAINT [DF_tblAIAgent_NationalCode] DEFAULT ((0)),
[FirstName] [NVARCHAR](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Name] DEFAULT (''),
[LastName] [NVARCHAR](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Family] DEFAULT (''),
[IsActive] [BIT] NOT NULL
CONSTRAINT [DF_tblAIAgent_Active] DEFAULT ((1)),
[Counter] [INT] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_tblAIAgent]
PRIMARY KEY CLUSTERED
)
ALTER TRIGGER [dbo].[AgentInsert]
ON [dbo].[tblAIAgent]
INSTEAD OF INSERT
AS
BEGIN
DECLARE @AgentCode NVARCHAR(10)
DECLARE @NationalCode BIGINT
DECLARE @FirstName NVARCHAR(50)
DECLARE @LastName NVARCHAR(50)
DECLARE @IsActive BIT
DECLARE @CounterIs INT
SET @CounterIs = @@IDENTITY
SELECT
@AgentCode = AgentCode,
@NationalCode = NationalCode,
@FirstName = FirstName,
@LastName = LastName,
@IsActive = IsActive
FROM inserted
INSERT INTO tblAIAgent (NationalCode, FirstName, LastName, IsActive, AgentCode)
VALUES (@NationalCode, @FirstName, @LastName, @IsActive, 'Agent_' + CAST(@CounterIs AS NVARCHAR(4)))
END
Run Code Online (Sandbox Code Playgroud)
您在这里遇到一些问题:
该@@IDENTITY是一个系统函数包含时所生成的最后一个标识值INSERT,SELECT INTO或BULK COPY完成陈述。如果该语句不影响任何带有标识列的表,则@@IDENTITY返回NULL。如果插入了多行,生成了多个标识值,则@@IDENTITY返回最后生成的标识值。
就您而言,您有一个INSTEAD OF INSERT触发器,因此没有INSERT。
下面的查询是完全错误的,并且将给出错误的结果,仅当插入一行时,它才能按预期工作;如果多于1行,则这些变量将仅保留一行的值,而您将丢失其他值其他行,因为伪INSERTED可能包含1个或更多行
select @AgentCode=AgentCode,
@NationalCode=NationalCode,
@FirstName=FirstName,
@LastName=LastName,
@IsActive=IsActive
from inserted
Run Code Online (Sandbox Code Playgroud)
现在,在您的表上查找,您已经有一个IDENTITY列,因此完全不需要TRIGGER,您只需将计算列设为
CREATE TABLE [dbo].[tblAIAgent](
[AgentCode] AS 'Agent_' + CAST([Counter] AS VARCHAR(10)),
[NationalCode] [bigint] NOT NULL
CONSTRAINT [DF_tblAIAgent_NationalCode] DEFAULT ((0)),
[FirstName] [nvarchar](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Name] DEFAULT (''),
[LastName] [nvarchar](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Family] DEFAULT (''),
[IsActive] [bit] NOT NULL
CONSTRAINT [DF_tblAIAgent_Active] DEFAULT ((1)),
[Counter] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_tblAIAgent] PRIMARY KEY ([Counter])
);
Run Code Online (Sandbox Code Playgroud)
更新:
根据您的评论“不能再将计算列选作PK。我希望将此列作为FK放置在其他相关表中。我编写了触发器以获取列值而不是计算列,以便我可以选择该列作为主键”。您正在尝试使其成为一种,PRIMARY KEY因此您可以
CREATE TABLE T(
Counter INT IDENTITY(1,1) NOT NULL,
OtherCol INT,
Computed AS CONCAT('Agent_', CAST(Counter AS VARCHAR(10))) PERSISTED,
CONSTRAINT PKT PRIMARY KEY(Computed)
);
CREATE TABLE TT(
ReferenceComputedColumn VARCHAR(16) NOT NULL,
OtherColumn INT,
CONSTRAINT FK_ReferencedComputedColumn
FOREIGN KEY(ReferenceComputedColumn)
REFERENCES T(Computed)
)
INSERT INTO T(OtherCol) VALUES
(1), (2), (3);
INSERT INTO TT(ReferenceComputedColumn, OtherColumn) VALUES
('Agent_1', 10),
('Agent_3', 20);
SELECT *
FROM T LEFT JOIN TT
ON T.Computed = TT.ReferenceComputedColumn;
Run Code Online (Sandbox Code Playgroud)
也看到这篇文章Properly Persisted Computed Columns的Paul White。