patternMinor
Implementing uniqueness with Oracle
Viewed 0 times
withoracleuniquenessimplementing
Problem
For example, say I have something like
I have to implement uniqueness of
I see 2 ways.
1. Using
2. Just adding
Neither of them looks ideal to me, and I wonder what is the proper way to implement uniqueness in such case.
Thanks.
CREATE TABLE COMPANY(id int not null primary key, ...);
CREATE TABLE DEPARTMENT(id int not null primary key, company_id int not null,
CONSTRAINT FK_DEP_COMPANY_ID FOREIGN KEY(company_id) REFERENCES COMPANY(id),...);
CREATE TABLE EMPLOYEE(id int not null primary key, department_id int not null,
username varchar(30) NOT NULL, ...,
CONSTRAINT FK_EMPLOYEE_DEP_ID FOREIGN KEY(department_id) REFERENCES DEPARTMENT(id));I have to implement uniqueness of
EMPLOYEE.username within one company. I see 2 ways.
1. Using
AFTER statement level trigger on EMPLOYEE table (something similar to http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936 , case1)2. Just adding
company_id to EMPLOYEENeither of them looks ideal to me, and I wonder what is the proper way to implement uniqueness in such case.
Thanks.
Solution
Mostly just for my own amusement, you can do this with a materialized view which has a unique index:
Then attempting to insert an
Just for fun I put
I'm not saying this is a good idea, just that it's possible...
CREATE MATERIALIZED VIEW LOG ON COMPANY
WITH PRIMARY KEY, ROWID
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON DEPARTMENT
WITH PRIMARY KEY, ROWID (company_id)
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON EMPLOYEE
WITH PRIMARY KEY, ROWID (department_id, username)
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW xcheck_mv
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT c.id as company_id, lower(e.username) as username,
c.rowid as c_rowid, d.rowid as d_rowid, e.rowid as e_rowid
from company c, department d, employee e
where d.company_id = c.id
and e.department_id = d.id;
CREATE UNIQUE INDEX xcheck_ind ON xcheck_mv(company_id, username);Then attempting to insert an
employee record for a different department with the same username gives a unique constraint violation, although not until you commit:insert into company (id) values(1);
1 row created.
SQL> insert into department (id, company_id) values(1, 1);
1 row created.
SQL> insert into department (id, company_id) values(2, 1);
1 row created.
SQL> insert into employee (id, department_id, username) values(1,1,'Joe Bloggs');
1 row created.
SQL> insert into employee (id, department_id, username) values(2,2,'Joe Bloggs');
1 row created.
SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-00001: unique constraint (STACKOVERFLOW.XCHECK_IND) violatedJust for fun I put
lower() in the MV definition to catch the most basic workaround - so trying to insert 'joe bloggs' also fails - but this model is never going to be very robust.I'm not saying this is a good idea, just that it's possible...
Code Snippets
CREATE MATERIALIZED VIEW LOG ON COMPANY
WITH PRIMARY KEY, ROWID
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON DEPARTMENT
WITH PRIMARY KEY, ROWID (company_id)
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON EMPLOYEE
WITH PRIMARY KEY, ROWID (department_id, username)
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW xcheck_mv
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT c.id as company_id, lower(e.username) as username,
c.rowid as c_rowid, d.rowid as d_rowid, e.rowid as e_rowid
from company c, department d, employee e
where d.company_id = c.id
and e.department_id = d.id;
CREATE UNIQUE INDEX xcheck_ind ON xcheck_mv(company_id, username);insert into company (id) values(1);
1 row created.
SQL> insert into department (id, company_id) values(1, 1);
1 row created.
SQL> insert into department (id, company_id) values(2, 1);
1 row created.
SQL> insert into employee (id, department_id, username) values(1,1,'Joe Bloggs');
1 row created.
SQL> insert into employee (id, department_id, username) values(2,2,'Joe Bloggs');
1 row created.
SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-00001: unique constraint (STACKOVERFLOW.XCHECK_IND) violatedContext
StackExchange Database Administrators Q#11739, answer score: 2
Revisions (0)
No revisions yet.