情况:有一个Java应用程序从DB Oracle中读取数据。为简化起见,当前从“ USERS”表中读取电子邮件字段。现在,我必须修改该应用程序,以便可以阅读更多电子邮件地址,但是我无意修改引用此表的所有数十种现有查询。防范措施是添加一个“ EMAILS”表,该表仅包含“ id_user”和“ mail_address”字段(除PK“ id_mailaddr”外)。但是,由于数据不仅是由应用程序加载的,而且还由其他用户通过多种方法(Excel表,查询“全部插入”,sql loader等)加载的,因此我必须在数据库级别施加一致性条件。问题就在这里!我不知道Oracle和Pl-sql。如果我在新表中插入的电子邮件地址的“ id_user”已经存在于“ USERS”表中,那么我该如何写一个“检查”约束来强加该“ id_user”的电子邮件地址表“ USERS”必须与新表中匹配的表一致吗?
例如:
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!
答案 0 :(得分:0)
希望此触发代码有帮助-
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;
/
答案 1 :(得分:0)
如果我的理解正确,那么您要确保没有将id_user
,mail_address
组合插入到先前存在的{{1}中不存在的新EMAILS
表中}表?
这仅在临时设计时才有意义,因为对于任何给定的USERS
记录,您最多只能放置一个EMAIL
记录。 (我假设USERS
中的行必须是唯一的。)
但是,如果那是随身携带的东西(为此+1,喜欢它!),我认为您在说的是外键约束:
EMAILS
这将确保没有任何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;
后,将视图替换为真实表。