首页 > 解决方案 > PL/SQL Ttrigger 从具有相同行的 2 个表中选择数据

问题描述

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

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

元素:DON_SEND 和 DON_REICV 是指向表用户的 MANI(标签)的外键。

我正在尝试创建一个触发器,仅当 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;

你能帮我吗?

标签: plsql

解决方案


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

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'

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

顺便说一句,我变成varcharvarchar2; 看看他们之间的区别。

此外,这假设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')

推荐阅读