October 11, 2005 at 8:53 am
Question: When I create foreign key constraints in my tables, do they have any effect on insert/update/selects?
Thanks.
October 11, 2005 at 8:57 am
The server will have to validate that the data modifications you do do not break the fk constraint. Won't have any effects on the select unless you add indexes.
October 11, 2005 at 4:40 pm
Also, in regards to Updates, if you specified cascading updates, this will obviously have an effect on your data.
A.J.
DBA with an attitude
October 12, 2005 at 5:40 am
It also has an effect on the locking behavior (it is one of the best practices to index your FKs)...one such example to show how locking behavior gets effected because of the FK:
Two tables: TableA and TableB which are related by a foreign key relationship (See the script below).
DROP TABLE TABLEA
GO
ALTER TABLE TABLEA ADD CONSTRAINT PK_TABLEA PRIMARY KEY CLUSTERED (COL1)
GO
CREATE TABLE TABLEB (COL1 INT NOT NULL, COL2 VARCHAR(30) NOT NULL, COL3 VARCHAR(30))
GO
ALTER TABLE TABLEB ADD CONSTRAINT PK_TABLEB PRIMARY KEY CLUSTERED (COL1, COL2)
GO
ALTER TABLE TABLEB ADD CONSTRAINT FK_TABLEB_TO_TABLEA FOREIGN KEY (COL1) REFERENCES TABLEA (COL1)
GO
INSERT INTO TABLEA (COL1, COL2, COL3, COL4) VALUES (1, 'TEST', 1, 'TEST-SQL')
INSERT INTO TABLEA (COL1, COL2, COL3, COL4) VALUES (2, 'TEST2', 1, 'TEST-SQL2')
INSERT INTO TABLEA (COL1, COL2, COL3, COL4) VALUES (3, 'TEST3', 1, 'TEST-SQL3')
INSERT INTO TABLEB (COL1, COL2, COL3) VALUES (1, 'TEST', 'TEST-SQL')
GO
set cursor_close_on_commit off
set ansi_defaults off
BEGIN TRAN
UPDATE TABLEA SET COL4 = 'TEST-SQL1' WHERE COL1 = 2
--Do Not Commit Yet
set cursor_close_on_commit off
set ansi_defaults off
set transaction isolation level read uncommitted
begin tran
select * from tableA with (nolock) where col1 = 2
set lock_timeout 5000
INSERT INTO TABLEB (COL1, COL2, COL3) VALUES (2, 'TEST-MOD', 'TESTSQL1')
--you will get the lock timeout error after 5 seconds
--ROLLBACK
October 12, 2005 at 7:22 am
non-clustered PK on which table and why would this solve the problem?
October 12, 2005 at 12:54 pm
Non-clustered index on the PK of the parent table. You can try it out using the scripts given above.
The pages in the data chain and the rows in them are ordered on the value of the clustered index key so, when the PK of the parent table is a clustered index, you will see that the lock output will be like this:
spid blocked object_name mode indid
54 0 TABLEA IX 0
54 0 TABLEA IX 1
54 0 TABLEA X 1
55 54 TABLEA IS 0
55 54 TABLEA IS 1
55 54 TABLEA S 1
55 54 TABLEB IX 0
55 54 TABLEB IX 1
55 54 TABLEB X 1
As you can see, the second session (55) is trying to take an implicit S lock on the parent table on the clustered index (indid = 1) and since the first session (54) already has an exclusive lock on it, the second session gets blocked.
After changing the index to be a non-clustered index, the select will be satisfied off the non-clustered index itself without any need to go to the data pages.
spid blocked object_name mode indid
54 0 TABLEA IX 0
54 0 TABLEA X 0
55 0 TABLEB IX 0
55 0 TABLEB IX 1
55 0 TABLEB X 1
Hth
Viewing 6 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply