Oracle 创建触发器以检查冲突
我的任务是检查在客户时间表上插入或更新团体健身课程时,是否与日期和时间冲突。谁能帮帮我吗。这些是我的桌子:Oracle 创建触发器以检查冲突,oracle,plsql,triggers,Oracle,Plsql,Triggers,我的任务是检查在客户时间表上插入或更新团体健身课程时,是否与日期和时间冲突。谁能帮帮我吗。这些是我的桌子: Name Null Type ------------- -------- ------------ CUSTOMER_T_ID NOT NULL NUMBER(38) C_DATE NOT NULL TIMESTAMP(6) TIMETABLE_ID NOT NULL NUMBER(38) CUSTOMER_ID
Name Null Type
------------- -------- ------------
CUSTOMER_T_ID NOT NULL NUMBER(38)
C_DATE NOT NULL TIMESTAMP(6)
TIMETABLE_ID NOT NULL NUMBER(38)
CUSTOMER_ID NOT NULL NUMBER(38)
Desc Timetable
Name Null Type
----------------- -------- ------------
TIMETABLE_ID NOT NULL NUMBER(38)
CLASS_DAY NOT NULL VARCHAR2(50)
CLASS_LOCATION NOT NULL VARCHAR2(50)
CLASS_START_TIME NOT NULL TIMESTAMP(6)
CLASS_FINISH_TIME NOT NULL TIMESTAMP(6)
WORKOUT_CLASS_ID NOT NULL NUMBER(38)
TRAINER_ID NOT NULL NUMBER(38)
Desc Workout_class
Name Null Type
---------------- -------- -------------
WORKOUT_CLASS_ID NOT NULL NUMBER(38)
NAME NOT NULL VARCHAR2(20)
WORKOUT_TYPE NOT NULL VARCHAR2(200)
EQUIPMENT_USED NOT NULL VARCHAR2(200)
RESULTS NOT NULL VARCHAR2(200)
COST NOT NULL FLOAT(126)
INTENSITY_LEVEL NOT NULL VARCHAR2(50)
CLASS_DURATION NOT NULL NUMBER(38)
Desc Customers
Name Null Type
---------------- -------- -------------
CUSTOMER_ID NOT NULL NUMBER(38)
FIRST_NAME NOT NULL VARCHAR2(50)
LAST_NAME NOT NULL VARCHAR2(50)
AGE NOT NULL NUMBER(38)
ADDRESS NOT NULL VARCHAR2(100)
CITY NOT NULL VARCHAR2(50)
MOBILE_PHONE NOT NULL NUMBER(10)
EMAIL VARCHAR2(50)
PICTURE BFILE()
CUSTOMER_TYPE_ID NOT NULL NUMBER(5)
触发器正在编译,但当我尝试将同一客户插入同一时间表时,他已经进入了该时间表,没有引发错误,但插入了行
create or replace trigger timetableconflict
before insert or update on customer_timetable
for each row
begin
if :new.customer_T_ID = :old.Customer_T_ID and :new.Customer_ID = :old.Customer_ID
then
raise_application_error(-20000,'customer cannot enrol into same class again');
end if;
end;
你的触发器正在比较。插入新行时,表中没有旧行,因此该记录中的所有字段都为空;因此,你的比较不匹配。您不能将任何内容与null进行比较,但这是一个单独的讨论。插入时无法匹配您使用的条件。更新时,将更新行中字段的现有值与更新的新值进行比较;因此,您当前的意思是更新必须更改customer\t\u id和customer\u id。除此之外,customer\t\u id可能应该是主键,因此更改通常不是一个好主意
所以我认为你误解了旧的含义。看起来customer\t\u id引用是一个错误,您试图确保表中没有该customer的记录,但OLD并没有告诉您这一点,因为它只引用受语句影响的当前行,而不是表中的任何其他行
根据你在问题中所说的,我不认为这实际上是你的最终目标——我认为你不希望客户有两次相同的时间表
鉴于OLD不能满足您的需要,您可能会考虑查询该表以查看这样一行是否已经存在。但你不能轻易地在一个触发器中做到这一点;如果您一次插入或更新多行,那么您将得到一个变异表错误。很容易滥用触发器,试图让它们做一些它们不是为之设计的事情
强制唯一性的正常方法是使用或唯一的复合键,而不是触发器:
alter table customer_timetable
add constraint timetableconflict unique (customer_id, timetable_id);
这也将创建一个唯一的索引来备份它;您可以直接创建一个唯一的索引,但声明约束更显式。这不是一个很好的约束名称,但我刚刚复制了您将要调用的触发器
您可以阅读更多关于:
与强制执行相同规则的触发器相比,约束更容易编写,也不容易出错。但是,触发器可以强制执行一些约束无法执行的复杂业务规则。Oracle强烈建议您仅在以下情况下使用触发器来约束数据输入:
当子表和父表位于分布式数据库的不同节点上时强制引用完整性
强制实施无法使用约束定义的复杂业务或引用完整性规则
您所描述的内容不属于这些类别。您还有多远?本网站的目的不是为您从头开始工作。如果:new.CUSTOMER\u t\u ID=:old.CUSTOMER\u t\u ID=:new.CUSTOMER\u ID=:old.CUSTOMER\u ID,则在更新每行的CUSTOMER\u时间表之前创建或替换触发器trig1,然后引发应用程序错误-20000,‘存在冲突’;如果结束;终止通常,这将通过一个唯一的约束来实现。真的需要扳机吗?