如何防止使用pl-sql中的触发器将空数据插入表行

时间:2013-03-25 14:15:02

标签: sql plsql oracle11g sqlplus plsqldeveloper

我正在尝试在PL / SQL中插入触发器之前创建,这会阻止将空数据插入表格行。 (强制执行非空条件并阻止插入数字或特殊字符的触发器。

这是我创建的表格。

CREATE TABLE CUSTOMER 
(
  CUSTOMER_ID INTEGER 
, CUST_FORENAME VARCHAR2(50) NOT NULL 
, CUST_SURNAME VARCHAR2(50) NOT NULL 
, GENDER CHAR(1) 
, EMAIL_ADDRESS VARCHAR2(30) NOT NULL 
, CONSTRAINT CUSTOMER_PK PRIMARY KEY (CUSTOMER_ID)
  ENABLE 
);

我创建的触发器。

create or replace
TRIGGER CUS_MAND before insert OR update on CUSTOMER
begin
  CASE
    WHEN :NEW.CUST_FORENAME = NULL
      THEN DBMS_OUTPUT.PUT_LINE ('Please enter customer forename.');
    WHEN :NEW.CUST_SURNAME = NULL
      THEN DBMS_OUTPUT.PUT_LINE ('Please enter customer surname.');
    WHEN :NEW.EMAIL_ADDRESS = NULL
      THEN DBMS_OUTPUT.PUT_LINE ('Please enter customer email address.');
  END CASE;
END;

但是这个触发器无法成功运行。有人可以帮我解决问题吗?

2 个答案:

答案 0 :(得分:4)

正如@APC指出的那样,使用NOT NULL约束比使用触发器更有意义。

但是,如果要使用触发器,则应该引发错误而不是仅仅打印到DBMS_OUTPUT,因为

  • 打印邮件不会阻止插入错误的数据
  • 通常,INSERTS / UPDATES将由某种客户端程序运行,而DBMS_OUTPUT将不会显示在此客户端程序中

除此之外,你的触发器中还有一些错误:

  • 您需要将触发器声明为FOR EACH ROW,否则,您将无法使用:NEW和:OLD(因为您的触发器将按语句触发一次,而不是每行一次
  • 您的CASE语句缺少DEFAULT分支,因此如果所有检查都成功,您将在执行期间收到错误消息;我改用IF而不是

一种可能的解决方案:

create or replace trigger CUS_MAND before insert OR update on CUSTOMER
for each row        
begin
  if :NEW.CUST_FORENAME is NULL THEN
    RAISE_APPLICATION_ERROR(-20001,
                            'Please enter customer forename.');
  end if;
  if :NEW.CUST_SURNAME is NULL THEN
    RAISE_APPLICATION_ERROR(-20002,
                            'Please enter customer surname.');
  end if;
  if :NEW.EMAIL_ADDRESS is NULL THEN
    RAISE_APPLICATION_ERROR(-20003,
                            'Please enter customer email address.');
  END if;
END;

在这里,我使用RAISE_APPLICATION_ERROR来引发用户定义的异常;您可以对所有错误使用相同的错误编号(-20001),也可以使用该编号来区分它们。

答案 1 :(得分:0)

您正在以错误的方式检查空值:

:NEW.CUST_FORENAME = NULL

空值检查必须使用“is null”或“not not null”。平等操作员不起作用。没有什么与NULL相同或不同。

所以,如果A:= null:

a = Null => false
a != null => false
a is null => true
a is not null => false

另外,你的触发器应该是Frank Schmitt指出的“每行”。

如果您的验证很简单,使用非空约束或检查约束可能是最佳选择。