Primary Key ve Foreign Key
Primary Key’ler tabloda unique’liği sağlar. Bir kolona primary key koyduğunuz da o kolona girilen bir değer sonraki gelecek insertler için tekrar girilemez. Örneğing ID kolonuna primary key koydunuz ve ilk insert’ünüzde 1 değerini set ettiniz. İkinci insert’ünüzde tekrar 1 değerini veremezsiniz. Primary Key tanımlı bir kolona null değer girilemez. Eğer unique’liği sağlayan bir kolonunuz varsa bu kolon üzerine primary key koyabilirsiniz. Yada Identitiy koyarak unique’liği sağlayabilirsiniz. Bir tabloda sadece bir tane Primary Key tanımlayabiliriz. Ama birden çok kolonu bir araya getirerek de Primary Key tanımlanabilir. Buna Composite Key denir.
Primary Key’lerin diğer bir özelliği de Foreing Key ile eşleştirilmesidir. Örneğin Şehir Tablosunda ID isimli kolona primary key koydunuz. Diğer kolon ismi ise SehirAdi olsun. SehirOzellikleri isminde başka bir tablomuz olsun. Bu tabloda da SehirID isimli bir kolonumuz ve Sehre ait diğer özellikleri barındıran bazı özellikler olsun. Sehir tablosundaki ID kolonu Primary Key, SehirOzellikleri tablosundaki SehirID isimli kolonuda ForeignKey olarak set ettiğimizde SehirOzellikleri tablosundaki ilgili şehre ait tüm kayıtlar silinmeden Sehir tablosundaki ilgili şehre ait kaydı silinemez hale getirmiş oluruz. Bu şekilde veri bütünlüğümüzü korumuş oluruz. Örneğimizi uygulamalı olarak gerçekleştirelim. Aşağıdaki 2 scriptle sehir ve sehirozellikleri tablolarını oluşturalım.
Aşağıdaki script ile sehir tablosunu oluşturalım.
USE [Test] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[sehir]( [ID] [int] IDENTITY(1,1) NOT NULL, [SehirAdi] [varchar](250) NULL, CONSTRAINT [PK_Sehir] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO
Aşağıdaki script ile de sehirozellikleri tablosunu oluşturalım.
USE [Test] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[sehirozellikleri]( [ID] [int] IDENTITY(1,1) NOT NULL, [SehirID] [int] NOT NULL, [MeshurYiyecek] [varchar](50) NULL, [MeshurIcecek] [varchar](50) NULL ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO
Aşağıdaki script ile de sehirozellikleri tablosundaki SehirID kolonuna primary kolonu sehir tablosundaki ID kolonu olan bir foreing key tanımlayalım. Scriptte de gördüğünüz üzere ForeingKey’i sehirozellikleri tablosundaki SehirID kolonuna koyduk. Referans olarak ta sehir tablosundaki ID kolonunu baz almasını söyledik.
ALTER TABLE [dbo].[sehirozellikleri] WITH CHECK ADD CONSTRAINT [FK_sehirozellikleri_Sehir] FOREIGN KEY([SehirID]) REFERENCES [dbo].[sehir] ([ID]) GO ALTER TABLE [dbo].[sehirozellikleri] CHECK CONSTRAINT [FK_sehirozellikleri_Sehir] GO
Aşağıdaki script ile sehir tablosuna bir kayıt ekleyelim. Gördüğünüz gibi sadece SehirAdi kolonuna değer girdik. Çünkü ID kolonuna 1 er 1 er artan bir identitiy koyduk. Yani her kayıt eklendiğinde ID kolonuna 1 er 1 er artacak şekilde otomatik değerler gelecek.
INSERT INTO [dbo].[sehir]([SehirAdi]) VALUES ('Adana')
Aşağıdaki gibi sehirozellikleri tablomuza da bir kayıt eklemeye çalışalım.
INSERT INTO [dbo].[sehirozellikleri]([SehirID],[MeshurYiyecek],[MeshurIcecek]) VALUES (2,'Kebap','Şalgam')
Yukarıdaki script’i çalıştırdığımızda aşağıdaki gibi hata alacağız.
Hatanın sebebi ise sehir tablosunda 2 ID’sine sahip bir sehrin olmaması.
Şimdi sehir tablosuna bir select çekip duruma bir bakalım.
Gördüğünüz gibi ID’si 1 ve SehirAdi da Adana. Script’i aşağıdaki gibi çalıştırdığımızda kaydın eklendiğini göreceğiz.
INSERT INTO [dbo].[sehirozellikleri]([SehirID],[MeshurYiyecek],[MeshurIcecek]) VALUES (1,'Kebap','Şalgam')
Peki sehir tablomuzu delete etmeye çalıştığımızda ne olacak aşağıdaki script ile bunu görelim.
USE [Test] GO DROP TABLE [dbo].[sehir] GO
Aşağıdaki gibi hata alacağız. Sehir tablosuna foreignkey ile sehirozellikleri tablosu bağlı olduğu için silmemize izin vermeyecek. Sehir tablosunu silebilmemiz için öncelikle sehirozellikleri tablosundaki foreign key’i silmemiz gerekir.
Şimdi aşağıdaki script yardımıyla sehir tablosunda ID’si 1 olan satırı silmeye çalışalım.
USE [Test] GO DELETE FROM [dbo].[sehir] where ID=1 GO
Aşağıdaki gibi hata verecektir. Sebebi ise sehirozelliklerinde SehirID’si 1 olan kaydın var olması.
Önce sehirozelliklerindeki ID’si 1 olan değerleri aşağıdaki gibi silip sonra yukarıdaki script’i tekrar çalıştırırsak başarılı bir şekilde silme işlemi gerçekleşecektir.
USE [Test] GO DELETE FROM [dbo].[sehirozellikleri] where SehirID=1 GO
Örnekte de gördüğünüz gibi Primary Key ve Foreign Key kullanarak bu ve benzeri bir çok ilişki ile veri bütünlüğümüzü garanti altına alabiliriz.
ON CASCADE DELETE ve ON CASCADE UPDATE eklentileri ile foreing key’in davranış şeklini değiştirebilirsiniz.
Detayları “ON DELETE CASCADE ve ON UPDATE CASCADE Nedir ve Nasıl Kullanılır” isimli makalede bulabilirsiniz.
teşekkürler çok güzel bir site ve çok güzel konular işlemişsiniz.
tekrar teşekkürler.
nacizane bir öneri : konular youtube ile video olarak işlenebilse süper olur.
Size bir soru sormak istiyorum. Elimde 2 tablo var. Bu tablolardan 1.sindeki kolonlardan 1 tanesini pk olacak. Diğer tabloda bu pk kolon yine olacak ve yine pk olacak. Bu kolonlar arası ilişkiyi foreign key ile bağlayabilir miyim?
Evet yapabilirsiniz. Ama primary key unique olduğu için one to one relationship olabilir. Yani bir tablodaki ilgili sütun’un diğer tablo’da sadece bir karşılığı olabilir.