插入触发器无法正常工作

时间:2009-09-19 06:08:20

标签: sql-server

我在已删除的用户表中创建了以下触发器,必须从userlogin表中删除相应的记录。

触发器涉及以下声明:

CREATE TRIGGER trgInsert_ToDeleteFromUserLogin on DELETEDUSER
FOR INSERT
AS

BEGIN

DECLARE
@UserName nvarchar(50),
@UserType nvarchar(30),
@Reason nvarchar(max)

SELECT @UserName = USERNAME, @UserType = UserType, @Reason = Reason FROM INSERTED 
INSERT INTO DELETEDUSER (USERNAME,USERTYPE,REASON) VALUES(@USERNAME,@USERTYPE,@REASON)
DELETE FROM USERLOGIN WHERE USERNAME = @UserName

end

但是当我在deleteduser表中插入记录时,相应的记录将从userlogin表中删除,但不会插入到deleteduser表中。

上述触发器不会产生任何错误,但是当我尝试在已删除的用户表中插入记录时,我注意到该记录已从UserLogin表中删除,但同样没有插入DeletedUser表中。

供您参考我包括deleteduser和userlogin的表结构如下:

Deleted User

CREATE TABLE DELETEDUSER
(
DeletedUserID int identity(1,1),
UserName nvarchar(max),
UserType nvarchar(30),
Reason nvarchar(max)
)

--ALTERING DELETEDUSER TABLE TO SPECIFY THE SIZE OF USERNAME COLUMN FOR IMPOSING FOREIGN KEY CONSTRAINT

ALTER TABLE DELETEDUSER ALTER COLUMN UserName nvarchar(50)

--ALTERING DELETEDUSER TABLE TO ADD FOREIGN KEY CONSTRAINT

ALTER TABLE DELETEDUSER ADD CONSTRAINT fk_UserName Foreign key (UserName) references UserLogin(UserName) on delete cascade


USERLOGIN TABLE:

CREATE TABLE USERLOGIN
(
UserID int identity(1,1) not null,
UserName nvarchar(50) not null,
Password nvarchar(50) not null
)

--ALTER TABLE USERREGISTRATION TO ADD PRIMARYKEY

ALTER TABLE USERLOGIN ADD CONSTRAINT pk_UserName primary key(UserName)

请帮我修改我应该在deleteduser表中插入行并从userlogin表中删除(删除)它。

提前致谢!

3 个答案:

答案 0 :(得分:2)

您的触发器是“AFTER”触发器(默认值),而不是“INSTEAD OF”。使用AFTER触发器,“契约已经完成” - 即插入DeletedUser已经发生,所以你需要INSERT语句。

DeletedUser和UserLogin之间的外键关系完全错误。根据您的描述,这些表是互斥的:在DeletedUser中拥有一个用户意味着他们不应再在UserLogin中,并且让用户在UserLogin中意味着他们也不会是DeletedUser。

所以,删除外键关系,试试这个:

CREATE TRIGGER trgInsert_ToDeleteFromUserLogin on DELETEDUSER FOR INSERT AS
BEGIN
  DELETE FROM UserLogin WHERE EXISTS (SELECT NULL FROM INSERTED WHERE
    INSERTED.USERNAME = UserLogin.USERNAME)
END

编辑:正如Shannon在下面提到的,这个代码将正确处理同时插入多个记录的情况,这与原始代码的单行假设形成对比。用例(禁用用户)一次只建议一个插入,但构建触发器对插入/删除的元表中的整个记录​​集进行操作会更好(也更容易)。

另外,通过使用视图可以简化数据库设计。例如:

ALTER TABLE UserLogin ADD DeletedReason varchar(255) NULL

CREATE VIEW ActiveUser AS SELECT * FROM UserLogin WHERE DeletedReason IS NULL

答案 1 :(得分:0)

为什么要在DeletedUser的INSERT触发器中插入DeletedUser?这已经发生了,因为这首先触发了触发器。删除那部分它应该没问题。

答案 2 :(得分:0)

假设插入的表中只有一行,则会写入您的触发器。 SQL没有行触发器(就像Oracle那样),它的触发器为一个语句触发一次,插入/删除的表将包含受语句影响的所有行

  

SELECT @UserName = USERNAME,@ UserType   = UserType,@ Reason = Reason FROM INSERTED

如果在一个语句中插入4行,会发生什么?

除了早期回复中注意到的问题之外,您还需要对触发器进行编码,以便它可以处理插入表中的任意数量的行。

有关SQL中触发器的详细介绍,请阅读:http://www.sqlservercentral.com/articles/Triggers/64214/