проверьте стоимость (или что-то лучше) - PullRequest
0 голосов
/ 05 июля 2018

Ситуация: есть Java-приложение, которое читает данные из БД Oracle. Для упрощения поле электронной почты в настоящее время считывается из таблицы «ПОЛЬЗОВАТЕЛИ». Теперь мне нужно изменить приложение, чтобы я мог читать больше адресов электронной почты, но у меня нет намерения изменять все десятки уже существующих запросов, которые ссылаются на эту таблицу. Эскамация заключалась в добавлении таблицы «EMAILS», содержащей (в дополнение к PK «id_mailaddr») только поля «id_user» и «mail_address». Но поскольку данные загружаются не только приложением, но и другими пользователями с использованием самых разных методов (таблицы Excel, запросы «вставка всего», загрузчик SQL и т. Д.), Я вынужден навязывать условие согласованности на уровне базы данных. И здесь кроется проблема! Я не знаю Oracle и Pl-sql. Как я могу написать ограничение "check", чтобы навязать, что, если "id_user" адреса электронной почты, который я вставляю в новую таблицу, уже существует в таблице "USERS", адрес электронной почты, которому соответствует этот "id_user" таблица «ПОЛЬЗОВАТЕЛИ» должна совпадать с совпадающей в новой таблице?
Например:

USERS                                     EMAILS
id_user  user       email                 id_mailaddr   id_user  mail_address
100      Smith      smith@yahoo.com       1             100      smith@yahoo.com        OK!
101      Brown      brown@gmail.com       2             101      brown@gmail.com        OK!
102      M.Scott                          3             105      scott@hotmail.com      NO!
103      J.Scott    scott@hotmail.com     4             103      j_scott@hotmail.com    NO!
104      P.Scott                          5             104      scotty@aol.com         OK!

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Если я правильно понимаю, вы хотите убедиться, что никакая комбинация id_user, mail_address не будет вставлена ​​в новую таблицу EMAILS, которая не существует в ранее существующей таблице USERS?

Это имеет смысл, только если это промежуточный дизайн, потому что вы не сможете поместить более одной записи EMAIL для любой данной записи USERS. (Я предполагаю, что строки в EMAILS должны быть уникальными.)

Но, если это эскамаж (+1 за это - обожаю!), Я думаю, вы говорите о ограничении внешнего ключа :

alter table users add constraint users_id_email_u1 
   UNIQUE (id_user, email);

alter table emails add constraint user_id_email_f1 
   FOREIGN KEY ( id_user, mail_address) REFERENCES users  ( id_user, email);

Это гарантирует, что никогда не будет EMAILS строк, которые не соответствуют тому, что есть в USERS.

Однако , это не обеспечит обратное! То есть может быть USERS строк, в которых нет нужной строки в EMAILS. Я не думаю, что вы спрашивали об этом случае в своем посте, но я думаю, что это может оказаться важным для вас. Итак, я бы предположил, что вы действительно хотите сделать:

CREATE OR REPLACE VIEW emails AS
  SELECT id_user, email mail_address
  FROM   users;

... и, возможно, это для обработки вставок в EMAILS «таблицу» ...

CREATE OR REPLACE TRIGGER emails_trg 
  INSTEAD OF INSERT
  ON emails
  FOR EACH ROW
BEGIN
  UPDATE users
  SET    email = :new.mail_address
  WHERE  id_user = :new.id_user;
END;

Затем, как только все ваши запросы будут обновлены до использования EMAILS, замените представление реальной таблицей.

0 голосов
/ 05 июля 2018

Надеюсь, этот код триггера поможет -

drop table users;
drop table email;

CREATE TABLE users
    (id_user integer, userz varchar2(7), email varchar2(17))
;

INSERT ALL 
    INTO users (id_user, userz, email)
         VALUES (100, 'Smith', 'smith@yahoo.com')
    INTO users (id_user, userz, email)
         VALUES (101, 'Brown', 'brown@gmail.com')
    INTO users (id_user, userz, email)
         VALUES (102, 'M.Scott', '')
    INTO users (id_user, userz, email)
         VALUES (103, 'J.Scott', 'scott@hotmail.com')
    INTO users (id_user, userz, email)
         VALUES (104, 'P.Scott', '')
SELECT * FROM dual
;



CREATE TABLE email
    (id_mailaddr int, id_user int, mail_address varchar2(19))
;


insert INTO email (id_mailaddr, id_user, mail_address)
         VALUES (3, 105, 'scott@hotmail.com');

insert INTO email (id_mailaddr, id_user, mail_address)
         VALUES (5, 104, 'scotty@aol.com');         

create or replace trigger email_trig
after insert on email
for each row
declare
v_cnt integer := 0;
mail_adr varchar2(64);
e exception;
begin
    if inserting then
        select email, count(*) into mail_adr, v_cnt from users where id_user = :new.id_user group by email;

        if v_cnt = 0 or mail_adr <> :new.mail_address then
            raise e;
        end if;
    end if;
exception
    when others then
        raise_application_error(-20000, 'Error inserting new email:- '||:new.mail_address);
end;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...