在oracle中创建一个触发器,它不允许使用if条件进行任何插入或更新

use*_*319 1 sql oracle plsql sqlplus

我有两张桌子 -

create table mobile
(
id int,
m_name  varchar(20),
purchase_date datetime
)


insert into mobile values('1','Samsung corby','12-JAN-12');
insert into mobile values('2','Nokia E5','15-MAR-12');
insert into mobile values('3','Sony Talk','10-FEB-12');



create table location
(
id int,
l_name varchar(20)
) 
insert into location values(1,'London');
insert into location values(2,'Washington');
insert into location values(3,'Mexico');
Run Code Online (Sandbox Code Playgroud)

我想创建一个触发器,以确保在12月份无法购买墨西哥的索尼移动设备.这意味着每当我尝试在ID为3且purchase_date为12月的移动表中插入数据时,触发器应该停止并且给出适当的信息.

我的代码是 -

create  or replace  trigger trg1
before insert or update
on mobile
for each row
declare
var1 number(4);  
begin
select id into var1 from location where l_name='Mexico';
    IF (:new.id = var1 and to_char(:new.purchase_date, 'MONTH') = 'DECEMBER') THEN 
        raise_application_error( -20001, 'THIS mobile CAN NOT BE PURCHASED NOW.');
    END IF; 
end; 
Run Code Online (Sandbox Code Playgroud)

触发器已创建,但当我尝试使用此代码插入此数据时 -

insert into mobile values('3','Sony Talk','10-JAN-11');
Run Code Online (Sandbox Code Playgroud)

触发器触发但出错 -

ORA-04098: trigger 'OPS$0924769.TRG1' is invalid and failed re-validation 
Run Code Online (Sandbox Code Playgroud)

而我的if代码也无法正常工作 -

    IF (:new.id = var1 and to_char(:new.purchase_date, 'MONTH') = 'DECEMBER') THEN 
        raise_application_error( -20001, 'THIS mobile CAN NOT BE PURCHASED NOW.');
    END IF; 
Run Code Online (Sandbox Code Playgroud)

它没有检查id和purchase_date.我把purchase_date给了JAN,所以在这种情况下触发器不应该触发.我很迷惑.

Jus*_*ave 7

  1. 您的触发器是使用编译错误创建的.如果show errors在创建触发器后键入,SQL*Plus将向您显示语法错误.
  2. Oracle没有DATETIME数据类型.purchase_date列的数据类型mobile必须是a DATE.
  3. 一旦我更正了定义mobile表中的错误,您发布的触发器就会在我的系统上编译并运行而不会出现错误
  4. 当您使用TO_CHAR格式掩码时MONTH,结果将使用空格右边填充到最长月份的长度(9个字符).由于DECEMBER只有8个字符,您的条件永远不会评估TRUE.您需要TRIM输出或使用fmMONTH不用空格填充输出的格式掩码.

就像是

create  or replace  trigger trg1
before insert or update
on mobile
for each row
declare
var1 number(4);  
begin
select id into var1 from location where l_name='Mexico';
    IF (:new.id = var1 and to_char(:new.purchase_date, 'fmMONTH') = 'DECEMBER') THEN 
        raise_application_error( -20001, 'THIS mobile CAN NOT BE PURCHASED NOW.');
    END IF; 
end; 
Run Code Online (Sandbox Code Playgroud)

你想要的更有可能.但这并不能解释为什么你的触发器会出现编译错误.