foreign key constraints

4
Causes and Cures of Tablespace Fragmentation Administration Tips Copyright © Howard Rogers 2001 10/18/2001 Page 1 of 4 Tablespace Fragmentation : Causes and Cures Fragmentation of a tablespace occurs when lots of pockets of free space are available within a tablespace, but none of them are of a sufficient size to house new extents for segments. Imagine that we are going to create the following tables within a tablespace: EMP - Initial Extent Size 4 blocks, Next Extent Size 5 blocks DEPT - Initial Extent Size 3 blocks, Next Extent Size 4 blocks We issue those commands, one after the other, and what do we have? (EMP is green-ish, DEPT is orangey). Now we start loading data into DEPT. It runs out of space in its initial extent, and has to acquire some more, and it does that a couple of times. Now our tablespace looks like this: (One Initial, followed by 2 next extents of 4 blocks each). At this point, we now start loading into EMP, and it acquires some extra extents to accommodate the data, too: (One Initial, followed by 2 extents of 5 blocks each). Now we decide that DEPT would be better off in some other tablespace altogether, so we move it (or drop it and re-create it elsewhere). That frees up the 11 blocks that DEPT was using, like this: Notice that, although the blocks used by DEPT are now free, I haven't simply shown them as white, empty blocks. That's because Oracle retains some 'memory' of where DEPT used to be... specifically, it remembers where the old extent boundaries for the table used to

Upload: rocker12

Post on 19-Feb-2016

218 views

Category:

Documents


1 download

DESCRIPTION

At this point, we now start loading into EMP, and it acquires some extra extents to accommodate the data, too: Fragmentation of a tablespace occurs when lots of pockets of free space are available within a tablespace, but none of them are of a sufficient size to house new extents for segments.

TRANSCRIPT

Page 1: Foreign Key Constraints

Foreign Key Constraints Administration Tips

Copyright © Howard Rogers 2001 10/18/2001 Page 1 of 3

Foreign Key Constraints Foreign key constraints are used to enforce referential integrity between tables. That is, you create a constraint on Table A, Column 5 declaring that it shall not contain values which have not previously been committed in Table B, Column 1. Table B in this example, containing the previously-validated data, is known as the "parent" table of the relationship. Table A, into which new records are being inserted which must reference the parent table, is known as the "child" table. To set up such a parent-child relationship at table creation time, you would issue the following sequence of commands: First the parent: CREATE TABLE CUSTOMERS ( CUSTID NUMBER CONSTRAINT CUST_CUSTID_PK PRIMARY KEY, CUSTNAME CHAR(20)); Now the child: CREATE TABLE ORDERS ( ORDERID NUMBER CONSTRAINT ORDERS_ORDERID_PK PRIMARY KEY, CUSTNUM NUMBER CONSTRAINT CUSTNUM_FK REFERENCES CUSTOMERS(CUSTID), ORDERVAL NUMBER(8,2)); A couple of things to notice here. Firstly, all constraints are named. Get into the habit of doing that, otherwise you have to live with the awful system-generated names that get assigned when constraint names are omitted. They're obscure and difficult to work with! Secondly, note that the column being referenced by the child is the Primary Key of the parent table. That is not always required -but at the very least, the column being referenced must have a unique constraint declared against it (in the world of Oracle, at least, a child cannot have two parents!). Primary keys are more usual, though. Thirdly, notice that the referenced column in the parent table is called 'custid', but in the child table, the equivalent column is called 'custnum'. The names of the related columns are not important, and can differ as much as you like. But the data types must agree. That is, if custid had been a char(15), then custnum would also have had to have been declared as a char datatype. If one is a number, the other must be too. If the two data types don't agree, you'll get an error: ORA-02267: COLUMN TYPE INCOMPATIBLE WITH REFERENCED COLUMN TYPE. However, the declared length of the fields doesn't necessarily have to tie up precisely (though you'll have problems later if they don't). A "number (5)" can quite happily reference a "number(6)" in the parent table.

Page 2: Foreign Key Constraints

Foreign Key Constraints Administration Tips

Copyright © Howard Rogers 2001 10/18/2001 Page 2 of 3

You may have used products such as Access, which allow updates to the parent table's data to be 'cascaded' down to the child. If, for example, we update a customer's number, we'd like all records in the child table that refer to that customer to pick up the new number. That can not be done in Oracle, at least not using the basic foreign key constraint definitions. You'd have to write a trigger instead. You can, however, specify that if a parent record is deleted then all child records should be deleted too (the default behaviour is that deletes of a parent record is simply not permitted if it would leave orphan child records behind). To do that, you issue this sort of command for the creation of the child table: CREATE TABLE ORDERS ( ORDERID NUMBER CONSTRAINT ORDERS_ORDERID_PK PRIMARY KEY, CUSTNUM CHAR(5) CONSTRAINT CUSTNUM_FK REFERENCES CUSTOMERS(CUSTID) ON DELETE CASCADE, ORDERVAL NUMBER(8,2)); Note the new key words “on delete cascade” there. Once this sort of cascading delete has been specified, we might see the following consequences: SQL> SELECT * FROM ORDERS; ORDERID CUSTID ORDERVAL ---------- ------ ---------- 1 789 350 2 789 7500 3 123 7500 SQL> SELECT * FROM CUSTOMERS; CUSTI CUSTNAME ----- -------------------- 789 SMITH 123 ROGERS SQL> DELETE FROM CUSTOMERS WHERE CUSTID='789'; 1 ROW DELETED. SQL> COMMIT; COMMIT COMPLETE. SQL> SELECT * FROM ORDERS;

Page 3: Foreign Key Constraints

Foreign Key Constraints Administration Tips

Copyright © Howard Rogers 2001 10/18/2001 Page 3 of 3

ORDERID CUSTID ORDERVAL ---------- ------ ---------- 3 123 7500 Notice how the delete of a single customer record resulted in the delete of 2 order records -but the SQL Plus confirmation of the delete somewhat (misleadingly) neglects to mention the child record deletions! Apart from these considerations, there is one extremely nasty aspect to foreign key constraints which it would seem that hardly any developer of my acquaintance is aware of (though they should be -it's in the Oracle documentation!). It is simply this: if I perform DML on any part of the PARENT table, the ENTIRE child table is locked out from all DML for the duration of the transaction. Selects can be done against the child table, because the lock involved is a share lock. But no DML whatsoever is permitted. That is an extremely expensive transaction! Fortunately, there's a fix for this: create an index on the column in the child table which is referencing the parent. If, pursuing the example we've seen earlier, I was to issue the command: CREATE INDEX ORDER_CUST_IDX ON ORDERS(CUSTNUM); ...which is an index on the child table, then no expensive locking of the entire child table takes place when I perform DML on the parent table. This business of child table locking is so nasty and surprising that it leads to quite a simple rule of thumb: whenever you declare a foreign key constraint on a child table, slap an index on that column afterwards. You may never use that index. It may be taking up unwelcome amounts of space, and its dead-weight presence will be slowing down your regular DML. But how much more unwelcome would it be not to be allowed to insert new orders because one customer wants to have his contact details amended? Incidentally, this issue is resolved in Oracle 9i: if there is no index on the child table's foreign key, then the table lock is taken as the DML on the parent table is started -but it is then immediately released. There is therefore no need to slap unnecessary indexes on child tables in 9i.