【发布时间】:2014-03-07 20:09:15
【问题描述】:
这篇文章比其他的要长一些,对此我深表歉意。所以如果你只是对此感兴趣,请帮助我。
CREATE TABLE software_manual(
item_no varchar(50),
title varchar(50) NOT NULL,
description varchar(500),
manufacturer varchar(50),
version varchar(50),
CONSTRAINT software_manual_pk PRIMARY KEY(item_no),
CONSTRAINT check_sw_item_no CHECK (title LIKE '[S]%')
);
CREATE TABLE cpy_item(
access_no int,
status varchar(50),
CONSTRAINT cpy_item_pk PRIMARY KEY(access_no),
CONSTRAINT check_status CHECK(status IN ('Borrowed','Lost','Stolen','Available'))
);
CREATE TABLE cpy_software_manual(
access_no int,
item_no varchar(50),
CONSTRAINT cpy_software_manual_pk PRIMARY KEY(access_no),
CONSTRAINT cpy_software_manual_fk FOREIGN KEY(item_no) REFERENCES software_manual(item_no),
CONSTRAINT cpy_software_manual_fk2 FOREIGN KEY(access_no) REFERENCES cpy_item(access_no)
);
我为上面的表格创建了一个视图,如下所示
CREATE VIEW vw_sw_manual (title,manufacturer,version,access_no)
AS
SELECT sm.title,sm.manufacturer,sm.version,csm.access_no
FROM software_manual sm, cpy_software_manual csm
WHERE sm.item_no=csm.item_no;
我想写一个 INSTEAD OF 触发器到 vw_sw_manual 视图来做下面提到的
我。如果插入的行包含表中存在的访问号,则使用插入的数据更新 software_manual 表的版本、标题和制造商列。
二。否则,如果在software_manual表中存在标题、制造商和版本,则在cpy_software_manual表中插入一个新行,其项目信息引用software_manual表的现有行
三。否则,在 software_manual 和 cpy_software_manual 表中插入行以反映新信息。
我写了一个触发器如下,它包含一些逻辑错误。 在第二部分。我的问题@item_no 在我的触发器中得到空值。谁能帮我解决这个问题?
alter TRIGGER tr_sw_vw_insert
ON vw_sw_manual INSTEAD OF INSERT
AS
BEGIN
DECLARE @insertAccessNo int
DECLARE @title varchar(50)
DECLARE @manufacturer varchar(5)
DECLARE @version varchar(50)
DECLARE @itemNo varchar(50)
DECLARE @maxAccessNo int
SELECT @maxAccessNo=MAX(access_no) FROM cpy_software_manual;
SELECT @insertAccessNo=access_no,@title=title,@manufacturer=manufacturer,@version=version FROM inserted;
IF(@insertAccessNo IS NOT NULL)
BEGIN -- if @insertAccessNo IS NOT NULL do this
SELECT @itemNo=item_no FROM cpy_software_manual WHERE access_no=@insertAccessNo;
UPDATE software_manual SET title=@title,version=@version,manufacturer=@manufacturer
WHERE item_no=@insertAccessNo;
END
ELSE IF(@title IS NOT NULL AND @manufacturer IS NOT NULL AND @version IS NOT NULL)
BEGIN
INSERT INTO cpy_item(access_no,status) VALUES(@maxAccessNo+1,'Available');
SELECT @itemNo=item_no FROM software_manual
WHERE title=@title AND manufacturer=@manufacturer AND version=@version;
INSERT INTO cpy_software_manual(access_no,item_no) VALUES(@maxAccessNo+1,@itemNo);
END
ELSE
BEGIN-- else do this
DECLARE @maxItemNo int
SELECT @maxItemNo=MAX(item_no) FROM software_manual;
INSERT INTO software_manual(item_no,title,version,manufacturer)
VALUES(@maxItemNo+1,@title,@version,@manufacturer);
INSERT INTO cpy_item(access_no,status) VALUES(@maxAccessNo+1,'Available');
INSERT INTO cpy_software_manual(access_no,item_no) VALUES(@maxAccessNo+1,@maxItemNo+1);
END
END
【问题讨论】:
-
您是否在插入期间添加要引用的行?如果是这样,您需要参考
INSERTED表,而不是此时还没有数据的实际数据表。 -
ANd 触发器需要在假设插入/更新或删除多个记录的情况下编写,因此您不应为标量变量设置任何内容。
-
当插入数据查看时,触发器应该根据逻辑更新/插入数据。在这种情况下(即问题 ii.)INSERTED 表没有 item_no 列(主键),这就是我在实际表中获取数据的原因
-
@HLGEM 我是数据库编程的新手,你能提出一些建议吗?
-
可以用于学习目的。我学会了将 BL 逻辑放入数据库中的艰难方法会给您带来维护问题。触发器也只会让事情变得更糟(用于维护)。希望你好运=)
标签: sql sql-server tsql triggers sql-scripts