我想为insert update和Delete编写触发器。 O有一个名为(tbl_rank)的表,它具有主键(ID)。
ID Name Rank
1 A 1
2 B 2
3 C 3
4 D 4
5 E 5
现在我要插入新的排名,但条件是
1) if I enter 6 it will be 6
2) if I enter 7 it also should be 6 (I mean in sequence)
3) if I enter 2 than than entered rank will be 2 and 2 will be 3 and so on
删除触发器
1) if I delete 5 the rank should be 1 to 4
2) if I delete 2 the rank would be rearranged and 3 should be 2 and 4 would be 3 and so on
用于更新触发器
1) if I update 3 to 5 than 4 would be 3 and 5 would be 4
2) if I update 5 to 3 than 3 would be 4 and 4 would be 5
我写了插入和删除触发它的工作正常,但在更新中我得到不均匀的结果。
答案 0 :(得分:0)
你能不能将tbl_rank视为一个视图,那么你不需要任何触发器吗?要在视图中对它们进行排名,您可以使用窗口函数row_number()(按Id排序)
初始更新是如何进行的?如果您知道它是更新,那么您需要执行删除并仅插入受影响的范围。例如,将3更改为5.删除3到5的记录,然后使用不同的ID再次插入这3条记录。无论如何,更新语句基本上都是这样做
答案 1 :(得分:0)
假设id不是自动标识列。
CREATE TRIGGER trg_tbl_rank
ON tbl_rank
INSTEAD OF INSERT,DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @v_deleted_rank INT;
DECLARE @v_inserted_rank INT;
DECLARE @v_max_rank INT;
SELECT @v_deleted_rank = COALESCE(rank, 0) FROM deleted;
SELECT @v_inserted_rank = COALESCE(rank, 0) FROM inserted;
SELECT @v_max_rank = COALESCE(MAX(rank), 0) FROM tbl_rank;
IF @v_deleted_rank > 0
BEGIN
DELETE FROM tbl_rank
WHERE id = (SELECT id FROM deleted);
UPDATE tbl_rank
SET rank = rank - 1
WHERE rank > @v_deleted_rank;
END
IF @v_inserted_rank > 0
BEGIN
IF @v_inserted_rank <= @v_max_rank
BEGIN
UPDATE tbl_rank
SET rank = rank + 1
WHERE rank >= @v_inserted_rank;
INSERT INTO tbl_rank (id, name, rank)
SELECT id, name, @v_inserted_rank FROM inserted;
END
ELSE
INSERT INTO tbl_rank (id, name, rank)
SELECT id, name, @v_max_rank + 1 FROM inserted;
END
DECLARE @v_deleted_rank INT;
DECLARE @v_inserted_rank INT;
DECLARE @v_max_rank INT;
SELECT @v_deleted_rank = COALESCE(rank, 0) FROM deleted;
SELECT @v_inserted_rank = COALESCE(rank, 0) FROM inserted;
SELECT @v_max_rank = COALESCE(MAX(rank), 0) FROM tbl_rank;
IF @v_deleted_rank > 0
BEGIN
DELETE FROM tbl_rank
WHERE id = (SELECT id FROM deleted);
UPDATE tbl_rank
SET rank = rank - 1
WHERE rank > @v_deleted_rank;
END
IF @v_inserted_rank > 0
BEGIN
IF @v_inserted_rank <= @v_max_rank
BEGIN
UPDATE tbl_rank
SET rank = rank + 1
WHERE rank >= @v_inserted_rank;
INSERT INTO tbl_rank (id, name, rank)
SELECT id, name, @v_inserted_rank FROM inserted;
END
ELSE
INSERT INTO tbl_rank (id, name, rank)
SELECT id, name, @v_max_rank + 1 FROM inserted;
END
以下是要测试的查询:
的
的END
GO
的
答案 2 :(得分:0)
我想为插入更新编写触发器并删除我有一个名为(tbl_rank)的表,其中包含主键(ID)
请发布DDL,以便人们不必猜测架构中的密钥,约束,声明性参照完整性,数据类型等。了解如何遵循ISO-11179数据元素命名约定和格式规则。时态数据应使用ISO-8601格式。代码应该尽可能在标准SQL中,而不是本地方言。
这是SQL论坛上的最小行为。将“tbl_”放在表名上是一个经典的设计缺陷,称为“tbling”,列名也违反了ISO-11179规则。现在我们必须猜测键,数据类型等。这是我的猜测和清理。
CREATE TABLE Prizes
(prize_id INTEGER NOT NULL PRIMARY KEY,
prize_name CHAR(1) NOT NULL,
prize_rank INTEGER NOT NULL);
INSERT INTO Prizes
VALUES
(1, 'A', 1),
(2, 'B', 2),
(3, 'C', 3),
(4, 'D', 4),
(5, 'E', 5);
为何触发? RDBMS具有虚拟表和列。这不是一副穿孔卡或磁带文件。 VIEW始终是最新且正确的。
CREATE VIEW Prize_List
AS
SELECT prize_id, prize_name,
ROW_NUMBER() OVER (ORDER BY prize_id)
AS prize_rank
FROM Prizes;
但最好完全删除prize_id列并根据prize_rank列重新排列显示顺序:
CREATE TABLE Prizes
(prize_name CHAR(1) NOT NULL,
prize_rank INTEGER NOT NULL PRIMARY KEY);
现在使用过程根据需要操作表。
CREATE PROCEDURE Swap_Prize_Ranks (@old_prize_rank INTEGER, @new_prize_rank INTEGER)
AS
UPDATE Prizes
SET prize_rank
= CASE prize_rank
WHEN @old_prize_rank
THEN @new_prize_rank
ELSE prize_rank + SIGN(@old_prize_rank - @new_prize_rank)
END
WHERE prize_rank BETWEEN @old_prize_rank AND @new_prize_rank
OR prize_rank BETWEEN @new_prize_rank AND @old_prize_rank;
如果要删除几行,请记住用以下方法填补空白:
CREATE PROCEDURE Close_Prize_Gaps()
AS
UPDATE Prizes
SET prize_rank
= (SELECT COUNT (P1.prize_rank)
FROM Prizes AS P1
WHERE P1.prize_rank <= Prizes.prize_rank);