PL / SQL Ttrigger从具有相同行的2个表中选择数据

时间:2018-06-05 17:49:20

标签: plsql

我有一个小项目的问题。 我有这些表:

USER (TAG VARCHAR, NICKNAME VARCHAR, TAG_CLAN VARCHAR)
DONATION(DATE_DON DATE, DON_SEND VARCHAR, DON_REIC VARCHAR)

元素:DON_SEND和DON_REICV是表格用户的MANI(TAG)的外键。

我正在尝试制作一个触发器,只有在TAG_CLAN相同时才允许用户制作和接收捐赠

我试过这种方式,但它不起作用:

CREATE OR REPLACE TRIGGER CONTROLLO_USER_DONAZIONE
BEFORE INSERT ON DONAZIONE
FOR EACH ROW
DECLARE 
TAG_C1      UTENTE.NUM_CLAN%TYPE;
TAG_C2      UTENTE.NUM_CLAN%TYPE;
CLAN_DIFF   EXCEPTION;
BEGIN
SELECT U.NUM_CLAN INTO TAG_C1
FROM DONAZIONE D JOIN UTENTE U ON D.COD_UTENTE_EFFETTUA=U.TAG_USER
WHERE D.COD_UTENTE_EFFETTUA=(:NEW.COD_UTENTE_EFFETTUA);
SELECT U.NUM_CLAN INTO TAG_C2
FROM DONAZIONE D JOIN UTENTE U ON D.COD_UTENTE_RICEVE=U.TAG_USER
WHERE D.COD_UTENTE_RICEVE=(:NEW.COD_UTENTE_RICEVE);
IF TAG_C1<>TAG_C2 THEN
    RAISE CLAN_DIFF;
END IF;
EXCEPTION
    WHEN CLAN_DIFF THEN
        RAISE_APPLICATION_ERROR(-20003,'NON SIETE NELLO STESSO CLAN, QUINDI NON PUOI RICEVERE/DONARE CARTE!');
END;

你能帮我吗?

1 个答案:

答案 0 :(得分:0)

您发布的表格和触发器代码之间存在一些差异。使用这样的表:

CREATE TABLE utente
(
    TAG_USER                                VARCHAR2(10) PRIMARY KEY,
    NICKNAME                                VARCHAR2(10),
    NUM_CLAN                                VARCHAR2(10)
);

CREATE TABLE DONAZIONE
(
    DATE_DON                                DATE,
    COD_UTENTE_EFFETTUA                     VARCHAR2(10)     REFERENCES utente(TAG_USER),
    COD_UTENTE_RICEVE                       VARCHAR2(10)     REFERENCES utente(TAG_USER)
);

这可能是你的触发器:

CREATE OR REPLACE TRIGGER CONTROLLO_USER_DONAZIONE
    BEFORE INSERT
    ON DONAZIONE
    FOR EACH ROW
DECLARE
    TAG_C1                                  UTENTE.NUM_CLAN%TYPE;
    TAG_C2                                  UTENTE.NUM_CLAN%TYPE;
    CLAN_DIFF                               EXCEPTION;
BEGIN
    SELECT U.NUM_CLAN
      INTO TAG_C1
      FROM UTENTE U
     WHERE U.TAG_USER = :NEW.COD_UTENTE_EFFETTUA;

    SELECT U.NUM_CLAN
      INTO TAG_C2
      FROM UTENTE U
     WHERE U.TAG_USER = :NEW.COD_UTENTE_RICEVE;

    IF TAG_C1 <> TAG_C2
    THEN
        RAISE CLAN_DIFF;
    END IF;
EXCEPTION
    WHEN CLAN_DIFF
    THEN
        RAISE_APPLICATION_ERROR(-20003, 'NON SIETE NELLO STESSO CLAN, QUINDI NON PUOI RICEVERE/DONARE CARTE!');
END;

使用以下数据:

insert into utente(TAG_USER, NICKNAME, NUM_CLAN) values ('one', 'User one', 'Numbers');
insert into utente(TAG_USER, NICKNAME, NUM_CLAN) values ('two', 'User two', 'Numbers');
insert into utente(TAG_USER, NICKNAME, NUM_CLAN) values ('a', 'User a', 'Letters');

它的工作原理如下:

SQL> insert into donazione(DATE_DON, COD_UTENTE_EFFETTUA, COD_UTENTE_RICEVE) values (sysdate, 'one', 'two');

1 row created.

SQL> insert into donazione(DATE_DON, COD_UTENTE_EFFETTUA, COD_UTENTE_RICEVE) values (sysdate, 'a', 'two');
insert into donazione(DATE_DON, COD_UTENTE_EFFETTUA, COD_UTENTE_RICEVE) values (sysdate, 'a', 'two')
*
ERROR at line 1:
ORA-20003: NON SIETE NELLO STESSO CLAN, QUINDI NON PUOI RICEVERE/DONARE CARTE!
ORA-06512: at "ALEK.CONTROLLO_USER_DONAZIONE", line 23
ORA-04088: error during execution of trigger 'ALEK.CONTROLLO_USER_DONAZIONE'

代码中的问题是你做了一个连接,假设你插入的记录已经存在于表DONAZIONE中,这会得到一个no_data_found异常。

顺便说一句,我将varchar更改为varchar2;看看它们之间的区别。

此外,这假定NUM_CLAN始终为NOT NULL

编辑:

鉴于您需要处理空值的方式,您可以编辑IF

IF TAG_C1 <> TAG_C2

IF TAG_C1 <> TAG_C2 or TAG_C1 is null or TAG_C2 is null

或者,更紧凑,但不太可读:

IF nvl(TAG_C1, 'a value that a clan can never have') <> nvl(TAG_C2 , 'some other impossible value')