Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Weird behavior using a deferrable constraint (bug?)

martin.tanlerMar 7 2021

Reproducable on the latest express version.

The following steps lead to different results of one and the same query (during transaction, uncommited data):
Create Table containing a deferrable (INITIALLY IMMEDIATE) constraint
Set the constraint deferred
Insert 2 rows violating the constraint (no commit)
Execute query X resulting in 0 rows (instead of 2)
Delete all rows from table
Drop deferrable ( INITIALLY IMMEDIATE) constraint from table (and index)
Add deferrable ( INITIALLY DEFERRABLE) constraint to table
Insert 2 rows violating the constraint (no commit)
Execute query X resulting in 2 rows (hurray!!!)
Why does initially immediate/deferrable lead to different results of one and the same query?

-- 1.Create Table containing a deferrable (INITIALLY IMMEDIATE) constraint
create table TDEFERED_UK_BUG(
    PK  NUMBER(3) NOT NULL
    , A NUMBER(3) NOT NULL
    , B NUMBER(3) NOT NULL
    , constraint UK_DEFERED_UK_BUG UNIQUE(A,B) DEFERRABLE INITIALLY IMMEDIATE USING INDEX (CREATE INDEX UK_DEFERED_UK_BUG ON TDEFERED_UK_BUG(A,B) )
);


-- 2. Set the constraint deferred
set constraint UK_DEFERED_UK_BUG deferred;
-- 3. Insert 2 rows violating the constraint
insert into TDEFERED_UK_BUG(PK, A,B) values(0, 1, 2);
insert into TDEFERED_UK_BUG(PK, A,B) values(1, 1, 2);


-- 4. Execute query X resulting in 0 rows (instead of 2)
select root.* from TDEFERED_UK_BUG root 
    where root.A = 1 and exists(
        select * from TDEFERED_UK_BUG ex where 
            ex.PK != root.PK
            and ex.A = root.A
            and ex.B = root.B
    );
-- What is going on there? No Results?


-- 5. Delete all rows from table
delete from TDEFERED_UK_BUG;
-- 6. Drop deferrable ( INITIALLY IMMEDIATE) constraint from table
alter table TDEFERED_UK_BUG drop constraint UK_DEFERED_UK_BUG;
drop index UK_DEFERED_UK_BUG;
-- 7. Add deferrable ( INITIALLY DEFERRABLE) constraint to table
alter table TDEFERED_UK_BUG add (
    constraint UK_DEFERED_UK_BUG UNIQUE(A,B) DEFERRABLE INITIALLY DEFERRED USING INDEX (CREATE INDEX UK_DEFERED_UK_BUG ON TDEFERED_UK_BUG(A,B) )
    );
-- 8. Insert 2 rows violating the constraint
insert into TDEFERED_UK_BUG(PK, A,B) values(0, 1, 2);
insert into TDEFERED_UK_BUG(PK, A,B) values(1, 1, 2);


-- 9. Execute query X resulting in 2 rows (hurray!!!)
select root.* from TDEFERED_UK_BUG root 
    where root.A = 1 and exists(
        select * from TDEFERED_UK_BUG ex where 
            ex.PK != root.PK
            and ex.A = root.A
            and ex.B = root.B
    );
    
Comments
Post Details
Added on Mar 7 2021
6 comments
745 views