【SQL】约束与触发器2

3.修改约束

3.1给约束命名

按如下格式命名:

name CHAR(30) CONSTRAINT NameIsKey PRIMARY KEY
gender CHAR(1) CONSTRAINT NoAndro
                            CHECK (gender IN ('F','M'))
CONSTRAINT RightTitle
    CHECK (gender = 'F' or name NOT LIKE 'Ms.%')

3.2 修改表上的约束

①修改约束的检查时间

SET CONSTRAINT MyConstraint DEFERRED;

SET CONSTRAINT MyConstraint IMMEDIATE;

②用ALTER TABLE语句

删除约束 DROP

ALTER TABLE MovieStar DROP CONSTRAINT NameIsKey;
ALTER TABLE MovieStar DROP CONSTRAINT NoAndro;
ALTER TABLE MovieStar DROP CONSTRAINT RightTitle;

添加约束 ADD(注意,约束必须是要整个表遵守时才加)

ALTER TABLE MovieStar ADD CONSTRAINT NameIsKey
    PRIMARY KEY(name);
ALTER TABLE MovieStar ADD CONSTRAINT NoAndro
    CHECK (gender IN ('F','M'));
ALTER TABLE MovieStar ADD CONSTRAINT RightTitle
    CHECK (gender = 'F' OR name NOT LIKE 'Ms.%');

注意:SQL不会记住已经删除的约束,所以如果要添加之前删除的约束必须重新写一遍。

 

 四、断言

1.创建断言

CREATE ASSERTION 断言名 CHECK (条件)

2.使用断言

CREATE ASSERTION RichPres CHECK
    (NOT EXISTS
        (SELECT Studio.name
         FROM Studio, MovieExec
         WHERE presC# = cert# AND netWorth < 1000000
        )
    );

上面的断言不允许资金小于1000000的经理。

CREATE ASSERTION SumLength CHECK (10000 >= ALL
    (SELECT SUM(length) FROM Movies GROUP BY studioName)
);

上面的断言不允许电影公司的电影总长度超过10000分钟。

如果这个语句用CHECK约束写,是

CHECK ( 10000 >= ALL
    (SELECT SUM(length) FROM Movies GROUP BY studioName));

断言和CHECK的区别:

CHECK只在插入和修改时有效,但对删除不做检查,在有些情况下会导致约束不成立。

断言则在任何提及的关系改变时都会检查,确保条件成立。

3.删除断言

DROP ASSERTION 断言名

五、触发器

当特定事件发生时,触发器被激活。如果状态满足触发器中的条件,则该触发器相连的动作被执行。

例子:

1.不允许降低电影制作人的净资产

CREATE TRIGGER NetWorthTrigger
AFTER UPDATE OF netWorth ON MovieExec
REFERENCING
    OLD ROW AS OldTuple,
    NEW ROW AS NewTuple
FOR EACH ROW
WHEN (OldTuple.netWorth > NewTuple.netWorth)
    UPDATE MovieExec
    SET netWorth = OldTuple.netWorth
    WHERE cert# = NewTuple.cert#;

2.阻止电影制作人的平均资产降到500000.要对插入、删除、修改分别设置触发器。这里列出修改的:

CREATE TRIGGER AvgNetWorthTrigger
AFTER UPDATE OF netWorth ON MovieExec
REFERENCING
    OLD TABLE AS OldStuff,
    NEW TABLE AS NewStuff
FOR EACH STATEMENT
WHEN (500000 > (SELECT AVG(netWorth) FROM MovieExec))
BEGIN
    DELETE FROM MovieExec
    WHERE (name, address, cert#, netWorth) IN NewStuff;
    INSERT INTO MovieExec
        (SELECT * FROM OldStuff);
END;

3.以year为主键的一部分,防止主键为空。在插入前如果发现year为空则插入默认值1915

CREATE TRIGGER FixYearTrigger
BEFORE INSERT ON Movies
REFERENCING
    NEW ROW AS NewRow
    NEW TABLE AS NewStuff
FOR EACH ROW
WHEN NewRow.year IS NULL
UPDATE NewStuff SET year = 1915;

相关选项介绍:

AFTER/BEFORE:决定测试是在事件发生前还是发生后

可被触发的事件:UPDATEINSERTDELETE

OF 属性:UPDATE的可选项,如果选中,则只有列出的属性变化时才激活触发器。

WHEN语句:可选项,如果选择,则条件为真才执行后面的语句,否则一定执行后面的语句。

多个执行动作:用BEGIN, END括起来

OLD ROW AS/NEW ROW AS/OLD TABLE AS/NEW TABLE AS:引用表修改前后的元组和表

FOR EACH ROW/FOR EACH STATEMENT:行级触发器,语句级触发器。如果更新整个表,行级触发器要对修改的元组一次一个的执行;语句级触发器则只用执行一次。语句级触发器不能引用新旧元组,但可以引用新旧表;行级触发器则都可以引用。

插入元组则没有旧值,删除元组则没有新值

 

原文地址:https://www.cnblogs.com/dplearning/p/4883515.html