For simplicity (and since it captures the essence of my problem), suppose I have a table with data.
CREATE TABLE my_practice_table
(
my_id NUMBER(12),
field_2 VARCHAR2(20),
field_3 VARCHAR2(20)
);
I want to define a new constraint on the table that has the following logic:
For any new record x inserted into my_practice_table,
if (x.field_2 is null)
if [there exists a record y in the table such that
i.) y.my_id == x.my_id
AND
ii.) y.field_2 is not null
]
--do not insert x into the table
else
--there exists no such y in the table, so we insert x
else (x.field_2 is not null)
if [there exists a record y in the table such that
i.) y.my_id == x.my_id
AND
ii.) y.field_2 is null
]
--do not insert x into the table
else
--there exists no such y in the table, so we insert x
Example: Suppose my_practice_table had the following data
table1: [1 'hi' 'bye' ]
[2 'hello' 'adios']
[1 'hi' 'seeya']
The statement:
INSERT INTO table1
(my_id, field_2, field_3)
VALUES
(1, null, 'ciao');
won't work because there is already a record in table1 with my_id equal to 1 and field_2 not equal to null.
Example: Suppose my_practice_table had the following data:
table2: [1 'hi' 'bye' ]
[2 null 'adios']
[1 'hi' 'seeya']
The statement:
INSERT INTO table2
(my_id, field_2, field_3)
VALUES
(2, 'hola', 'this won't work');
won't work because there is already a record in table2 with my_id equal to 2 and field_2 equal to null.
My question is what is the way to go about this in Oracle syntax. The algorithm is simple enough, but I'm just not comfortable enough with Oracle syntax to get the job done.
Do I use a BEFORE INSERT Trigger? How do I scan for values in other fields of a particular row once I found a match on the field my_id? Is there a 'break' statement in Oracle that I can do to speed this up?
Any help or guidance to the right place to look for a possible solution would be appreciated. Thanks
Best Answer
If you query the table you're inserting into inside a trigger on that same table, you are likely to get "ORA-04091: table name is mutating, trigger/function may not see it." error. Check constraints cannot contain subqueries. Therefore your best option is to encapsulate logic for inserting data into a stored procedure and use that procedure instead of direct inserts.
I can assist you with writing the procedure, however, it seems to me that you have a logical flaw in your data model. Your example data shows that my_id is not a unique key for the table but rather that many rows may share the same value for my_id. So if one row with my_id = 1 has field_2 set to some value and for some other row field_2 is null, what is to be done? Don't you have a primary key in your table?
Anyways, if you want literally what you wrote in your post, you could do with something like
I didn't actually try out the procedure so it may have slight errors, but that's the general form it could take.