感谢阅读。我目前正在为一家假想商店开发一个大约10个实体的数据库。因此,主要实体是Customer_Order,此触发器的目的是在Customer_order中插入或更新行时检查客户的邮政编码是否为空。如果为null,则触发器应该发出警告。
CREATE OR REPLACE TRIGGER Check_Order
BEFORE INSERT OR UPDATE ON Customer_Order
for each row
DECLARE ShipAddress customer.ship_address.post_code%TYPE;
BEGIN
IF (ShipAddress = '') then
RAISE_APPLICATION_ERROR(-20103, 'Shipping Address is empty');
END IF;
END;
.
run
我知道没有“Else”,但除了更新它所做的表之外,我没有任何其他行动。 不要担心ShipAddress,我尝试使用更简单的属性,它根本不会触发。所有发生的事情是该行将被插入或更新,因此它不符合条件。我已经尝试了各种各样的方法,例如“if(Payment_No ='PAYM0001')也不起作用。是不是因为我使用的是每个而不是语句级触发器?
答案 0 :(得分:6)
Oracle将空字符串(即长度为零的字符串)静默转换为NULL。因此,您的列中永远不会有''
值。因此IF语句永远不会成立。您需要在该触发器中检查NULL:
IF (ShipAddress IS NULL) then
RAISE_APPLICATION_ERROR(-20103, 'Shipping Address is empty');
END IF;
但是你真的应该遵循Ben的建议并简单地将该列声明为NOT NULL,而不是使用触发器来检查它。
修改强>
您可以使用表格上的检查约束进行非空检查:
CREATE TABLE FOO
(
shipping_address ship_addres,
CONSTRAINT check_post_code CHECK (shipping_address.post_code IS NOT NULL)
)
答案 1 :(得分:1)
Oracle使用3个值逻辑,null为第3个值。某些事情可能是真实的,错误的或不存在的。 null
不存在,等于零。您不能使用相等运算符测试null。使用IF :new.ShipAddress is null
测试空值。
您还在触发器中错误地引用了列。无需声明任何内容,您必须引用:new
或:old
值。 This是一个很好的资源。
最好通过在表上放置约束来禁止空值,这样shipaddress
永远不能为空。见here。所以,
alter table my_table modify shipaddress not null;
将其添加到表中。最好在创建表时添加约束。这样做也会稍微加快速度,因为您不需要评估触发器。
修改强>
shipaddress
有一个完整的地址,可能是逗号分隔的?我肯定会建议将地址的每个部分分开,例如address1
,address2
,address3
,town
,county
,{{1} }。我是英国人,所以必要时改为postcode
,state
等。如果你需要做更多,更容易的事情,这会使数据的查询和操作。