SQL Server 2005 ile birlikte sunulan CTE (Common Table Expression – Ortak Tablo İfadeleri), bir sorgunun yürütülmesi anında elde edilmiş geçici sonuçlar bir veya daha fazla kere kullanılmasını sağlayan ifadelerdir. CTE bir table veya view olmayıp sadece bir sorgu ifadesidir. Yani geçici ve kalıcı tablolar gibi herhangi bir veri içermezler. Bir CTE’nin basit yazım biçimi aşağıdaki gibidir;
WITH expression_name [ ( column_name [,...n] ) ] AS ( CTE_query_definition )
CTE’ler WITH sözcüğüyle tanımlanır. CTE’lerin en önemli özelliği kendi kendini çağırabiliyor olması ve aynı sorgu içerisinden birden fazla çalıştırılabiliyor olmasıdır. Bu özelliğiyle CTE’ler daha çok recursive(Öz-yinelemeli) işlemler için geliştirilmiştir diyebiliriz. Örnek olarak hiyerarşik listeler için tercih edilir. Bu tür işlemler için geçici tablolar kullanılabiliyor olsa da CTE’ler daha iyi bir performans sağlar. En azından tablo okuma ve işlemler gibi herhangi bir log izi oluşturmaz.
CTE’ler table ve view yapılarından farklı olarak primary key, unique, not null, default. gibi constraint’ler desteklemez. Aslında olmayan birşeyden daha doğrusu sadece çağrıldıkları anda oluşan bir yapıdan bahsediyoruz.
CTE’ler yalnızca SELECT değil INSERT, UPDATE ve DELETE yapılarında da kullanılabilir.
Aşağıdaki içeriğe sahip Kategori ve Urun isminde 2 tablo olduğunu düşünelim.
Kategori tablosunu sorgulamayı en basit CTE yapısıyla şu şekilde yazabiliriz;
WITH cteKat(KategoriId, KategoriAdi) AS ( SELECT KategoriId, KategoriAdi FROM Kategori ) SELECT * FROM cteKat
Şimdi aralarında hiyerarşik ilişki bulunan kategorileri seviyelerine göre listeleyelim. Yani hangi kategori hangi kategoriye bağlı görünüyor.
WITH cteKat(KategoriId, KategoriAdi, UstKategoriAdi, Seviye) AS ( --Başlangıç Sorgusu SELECT KategoriId, KategoriAdi, CAST('' as VARCHAR(10)) UstKategoriAdi, 1 Seviye FROM Kategori WHERE UstKategoriId IS NULL UNION ALL --Biriktirme Sorgusu SELECT K1.KategoriId, K1.KategoriAdi, K2.KategoriAdi UstKategoriAdi, Seviye+1 Seviye FROM Kategori K1 INNER JOIN cteKat K2 ON K1.UstKategoriId=K2.KategoriId ) SELECT * FROM cteKat
Görüldüğü gibi cursor, while gibi döngüsel işlemler yapmadan kolayca kendine atıfta bulunan bir sorgu yazmış olduk. CTE ile yapılmış başka bir örnek için SQL Server Önceki Satırların Toplamı makalesine göz atılabilir.
Selam
WITH cteKat(KategoriId, KategoriAdi, UstKategoriAdi, Seviye)
AS
(
–Başlangıç Sorgusu
SELECT KategoriId, KategoriAdi, CAST(” as VARCHAR(10)) UstKategoriAdi, 1 Seviye
FROM Kategori WHERE UstKategoriId IS NULL
UNION ALL
–Biriktirme Sorgusu
SELECT K1.KategoriId, K1.KategoriAdi, K2.KategoriAdi UstKategoriAdi, Seviye+1 Seviye
FROM Kategori K1 INNER JOIN cteKat K2 ON K1.UstKategoriId=K2.KategoriId
)
SELECT * FROM cteKat
çalışmıyor.
Kodları neden kontrolsüz ekliyorsunuz siteye
bence senin tabloların hatalı sorguda bir problem yok
Bende hata aldım
Msg 240, Level 16, State 1, Line 2
Types don’t match between the anchor and the recursive part in column “UstKategoriAdi” of recursive query “cteKat”.
Selim Bey,
bu hatayı tablodaki KategoriAdi alanının türünün farklı olmasından alıyorsunuzdur. Kategori tablosunda KategoriAdi alanının tipi ne ise CTE’de de aynısını yazmanız gerekiyor. Benim örneğimde tablodaki KategoriAdi alanını türü VARCHAR(10) dur. Tablonun CREATE scripti şu şekildedir;
CREATE TABLE Kategori(
KategoriId INT,
KategoriAdi VARCHAR(10),
UstKategoriId INT
)
INSERT Kategori VALUES(1,’K1′,NULL)
INSERT Kategori VALUES(2,’K2′,NULL)
INSERT Kategori VALUES(3,’K11′,1)
INSERT Kategori VALUES(4,’K12′,1)
INSERT Kategori VALUES(5,’K21′,2)
INSERT Kategori VALUES(6,’K13′,1)
INSERT Kategori VALUES(7,’K121′,4)