PL / SQL Trigger выбирает данные из двух таблиц с той же строкой

Nicola Cantelli спросил: 12 мая 2018 в 04:09 в: plsql

У меня есть проблема с небольшим проектом. У меня есть следующие таблицы:

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

ЭЛЕМЕНТЫ: DON_SEND И DON_REICV ЯВЛЯЮТСЯ ЗНАЧИТЕЛЬНЫМ КЛЮЧОМ, КОТОРЫМИ УКАЗЫВАЮТСЯ МАНИ (TAG) Пользователь TABLE USER.

Я пытаюсь сделать триггер, который позволяет пользователям делать и получать пожертвования только в том случае, если TAG_CLAN тот же самый

Я пытался таким образом, но он не" t work:

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 ответ

Есть решение
Aleksej ответил: 12 мая 2018 в 07:55

Существуют некоторые различия между таблицами, которые вы опубликовали, и кодом вашего триггера. С такими таблицами:

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.

EDIT:

Учитывая способ обработки нулевых значений, вы можете отредактировать 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')
Nicola Cantelli ответил: 12 мая 2018 в 07:28
большое спасибо за помощь, но есть проблема, NUM_CLAN не является NOT NULL, потому что пользователь может не быть в каком-либо клане
Aleksej ответил: 12 мая 2018 в 07:34
Итак, что делать, если пользователь находится в клане, а другой нет? А что, если оба пользователя не в клане?
Nicola Cantelli ответил: 12 мая 2018 в 07:50
только пользователь того же клана может отправлять / получать карты. пользователь, который не находится в клане, не может отправлять / получать кому-либо.
Aleksej ответил: 12 мая 2018 в 07:55
просто показал путь. здесь может быть полезна некоторая логическая логика
Nicola Cantelli ответил: 12 мая 2018 в 08:08
большое вам спасибо за вашу помощь! Я так его оценил