在Oracle中使用触发器实现主键概念

问题描述 投票:0回答:1

我想使用触发器在一个表上实现主键概念(唯一+非空)。

这样我就可以避免重复和空值插入到表中。

此处示例:表

gt1
和列
product

我收到此错误:

ORA-00036:超出递归 SQL 级别的最大数量 (50)

CREATE TABLE gt1
(
    PRODUCT VARCHAR2(2), 
    T_DATE DATE,
    YEAR NUMBER(2)
);
'------ Trigger-----------------
create or replace trigger tg1 before insert on gt1
for each row
declare

msg varchar2(20);
N_prd varchar(2);
cnt number;
begin

N_prd := :new.product;
select count(*) into cnt from gt1 where product=n_prd;

dbms_output.put_line(N_prd || ' ,'|| cnt);

if N_prd is not null or N_prd <>'' 
 then 
   if cnt<>0 then 
      dbms_output.put_line(:new.product||' - Product is already exists');
      else 
      
      insert into gt1 values(:new.product,:new.T_DATE,:new.year);
     
     dbms_output.put_line('insert is success');
    end if;
 else 
    dbms_output.put_line(:new.product||' - is null');

end if;
end;
INSERT INTO gt1 
VALUES ('P1', sysdate + 1, 23);

请帮我解决这个问题。

sql oracle plsql
1个回答
0
投票

不要使用触发器。使用

PRIMARY KEY
约束,因为这就是它的设计目的。

ALTER TABLE gt1 ADD CONSTRAINT gt1__product__pk PRIMARY KEY;

如果您确实想使用触发器(不要),则使用

AFTER INSERT
触发器,并且
RAISE
如果表包含重复值或
NULL
值,则会出现异常,否则不执行任何操作并让插入成功:

CREATE TRIGGER tg1
  AFTER INSERT ON gt1
DECLARE
  cnt_null PLS_INTEGER;
  cnt_dup  PLS_INTEGER;
  NULL_VALUE EXCEPTION;
  PRAGMA EXCEPTION_INIT(NULL_VALUE, -1400);
BEGIN
  SELECT COUNT(COUNT(CASE WHEN product IS NULL THEN 1 END)),
         COUNT(CASE WHEN COUNT(*) > 1 THEN 1 END)
  INTO   cnt_null,
         cnt_dup
  FROM   gt1
  GROUP BY
         product
  HAVING COUNT(CASE WHEN product IS NULL THEN 1 END) > 0
  OR     COUNT(*) > 1;

  IF cnt_dup > 0 THEN
    RAISE DUP_VAL_ON_INDEX;
  END IF;

  IF cnt_null > 0 THEN
    RAISE NULL_VALUE;
  END IF;
END;
/

然后在同一语句中插入重复项:

INSERT INTO gt1 (product)
SELECT 1 FROM DUAL UNION ALL
SELECT 1 FROM DUAL;

失败:

ORA-00001: unique constraint (.) violated
ORA-06512: at "FIDDLE_PAKJMILXQHBGVOYNUEEG.TG1", line 18
ORA-04088: error during execution of trigger 'FIDDLE_PAKJMILXQHBGVOYNUEEG.TG1'

并插入

NULL
:

INSERT INTO gt1 (product) VALUES (NULL);

失败:

ORA-01400: cannot insert NULL into ()
ORA-06512: at "FIDDLE_PAKJMILXQHBGVOYNUEEG.TG1", line 22
ORA-04088: error during execution of trigger 'FIDDLE_PAKJMILXQHBGVOYNUEEG.TG1'

并插入奇异值:

INSERT INTO gt1 (product) VALUES (1);

成功了。

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.