[英]Oracle: Need help on triggers
大家好,又是我,我刚刚开始上 Oracle/数据库学位课程,几天前我发布了这个,得到了及时的答复,非常感谢。
跟进此事,考虑我有这两张表
CREATE TABLE CUSTOMER (
CustID NUMBER(5) NOT NULL,
CONSTRAINT CustID_PK PRIMARY KEY (CustID),
PlanTypeNo Number(1) NOT NULL,
CONSTRAINT PlanTypeNo_CustomerFK FOREIGN KEY (PlanTypeNo) REFERENCES PLANTYPE(PlanTypeNo),
CustName VARCHAR2(50) NOT NULL,
CustICNo VARCHAR2(9) NOT NULL,
CustTelNo VARCHAR2(8) NOT NULL,
CONSTRAINT UniqueCustomer UNIQUE (CustICNo,CustTelNo),
CONSTRAINT Exact_IC_Length CHECK (LENGTH(CustICNo) = 9),
CONSTRAINT Exact_Tel_Length CHECK (LENGTH(CustTelNo) = 8),
PaymentModePref VARCHAR2(15) NOT NULL,
CONSTRAINT PaymentModePref_Accepted CHECK (PaymentModePref IN ('Paypal','Cash','EFT')),
LastBillPaidDate DATE,
hasUnpaidBill NUMBER(1) NOT NULL,
CONSTRAINT UnpaidBill_Boolean CHECK (hasUnpaidBill IN ('0', '1')),
CompanyName VARCHAR2(50),
CompanyRegNo VARCHAR2(10),
CONSTRAINT If_NonResident CHECK ((((PlanTypeNo) = 1) OR (CompanyName IS NOT NULL AND CompanyRegNo IS NOT NULL)))
);
和
CREATE TABLE LOCATION (
LocationID NUMBER(6) NOT NULL,
CONSTRAINT LocationID_PK PRIMARY KEY (LocationID),
CustID Number(5) NOT NULL,
CONSTRAINT CustID_LocationFK FOREIGN KEY (CustID) REFERENCES CUSTOMER(CustID),
LocationName VARCHAR2(40) NOT NULL,
LocationAddress VARCHAR2(50) NOT NULL,
CONSTRAINT UniqueNameAddress_Location UNIQUE (LocationName, LocationAddress)
);
我在编码方面比较有经验,但不是数据库程序/脚本/查询。 您将如何为数据库创建一种方法(可能是约束?)来检查有未付账单的所有者是否想要添加新位置?
我尽可能比较 CustID 外键以返回到 CUSTOMER 表并检查它们是否有任何大于 60 天的 LastBillPaidDate,或者创建一个触发器,如果当前日期 - LastBillPaidDate > 60,则将 hasUnpaidBill 变为“1”,然后在尝试插入一行时检查 hasUnpaidBill 的值是否为 1
希望它不会太混乱,我明白了逻辑,但不知道如何为数据库实现它:|
再次感谢!
这是一个示例触发器。 编写触发器时,您可以查询其他表,但通常无法查询正在插入/更新的表。 因此可以查询 CUSTOMER,但您应该使用:NEW 对象来引用当前插入的 LOCATION 记录上的字段。
set define off
CREATE OR REPLACE TRIGGER LOCATION.LOC_CUSTOMER_UNPAID
BEFORE INSERT
FOR EACH ROW
DECLARE
has_unpaid varchar2(1);
unpaid_bill EXCEPTION;
PRAGMA EXCEPTION_INIT( unpaid_bill, -20001 );
BEGIN
select 'Y' into has_unpaid
from CUSTOMER c
where c.CustID = :new.CustID
and lastBillPaidDate < sysdate-60;
if has_unpaid = 'Y' then
raise_application_error( -20001, 'Cannot create new location: Customer has unpaid bill.' );
end if;
EXCEPTION when NO_DATA_FOUND then
null; -- ignore
END;
/
( set define off
不是绝对必要的,但一些 IDE 会感到困惑,并要求您将 :NEW 的值设置为绑定变量。)
我会说数据库可能不是这种逻辑的最佳位置。 您可以在触发器中执行此操作,但有时会有点尴尬 - 如果您无法捕获错误并显示友好消息,则从触发器引发错误消息回溯可能在客户端看起来很糟糕。
编辑:我在这里定义自定义错误消息。 过程有点曲折。 unpaid_bill EXCEPTION
表示我们正在创建一个新的错误类型, PRAGMA EXCEPTION_INIT(unpaid_bill, -20001)
表示将我们的错误与代码 #-20001 相关联,而raise_application_error(-20001)
表示引发/返回该错误代码。
为了提供更多背景信息,如果您想阻止用户做某事(例如,如果他们有未结帐单,则添加位置),您有几个选择:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.