Bu bölümde, T-SQL dilinin SELECT sorguları yazılmasındaki rolünü öğreneceğiz. Ayrıca T-SQL bileşenlerinden ve sorgu yazarken sağladıkları faydalardan bahsedeceğiz.

T-SQL hakkında

T-SQL, Microsoft’un endüstri standardı Structured Query Language’in uyarlamasıdır. 1970’lerin başlarında IBM’de yeni çıkan ilişkisel veri modelini desteklemesi için geliştirilmiştir. O zamandan beri de SQL sektöründe yaygın olarak benimsenmiştir. SQL, 1980’lerde Amerikan Ulusal Standartlar Enstitüsü (ANSI) ve Uluslararası Standardizasyon Örgütü’nün (ISO) standardı haline gelmiştir.

ANSI standardı, SQL-89 ve SQL-92 dahil birçok revizyon sürecinden geçmiştir. Bu standartlar tamamen ya da kısmen T-SQL tarafından desteklenmektedir. SQL Server ayrıca ANSI SQL-2008 ve ANSI SQL-2011 gibi daha sonra ortaya çıkan standartlardan gelen özellikleri de barındırmaktadır. Microsoft da bu dili, SQL Server’a özgü özellik ve işlevleri içerecek şekilde geliştirmiştir.

Microsoft’un T-SQL gibi, Oracle firmasının PL/SQL’i, IBM’in SQL PL’si ve Sybase’in de kendi T-SQL dilini geliştirmeyi sürdürmektedir.

T-SQL prosedürel bir dil değil, set-based ve declarative bir dildir. SQL Server’dan veri çekmek için bir sorgu yazdığınızda, sadece çekmek istediğiniz verileri tanımlamanız yeterlidir. Örneğin, Portland’da ikamet eden müşterilerin listesini almak istediğimizde aşağıdaki prosedür işler:

Her satırı teker teker gez.
Eğer şehir Portland ise satırı döndür, değilse devam et.
Bir sonraki satıra git.
Döngüyü sonlandır.

T-SQL gibi bir declarative dilde sadece çekmek istediğiniz kümeyi tanımlayan nitelikleri ve değerleri tanımlarsınız. Verilerin nasıl alınacağını belirtmeniz gerekmez, sadece verilerin ne olduğunu belirtmeniz yeterlidir. Örneğin şu psödokoda bir bakalım:

Şehri Portland olan tüm müşterileri döndür.

T-SQL ile SQL Server Database Engine, verilere erişmek ve eşleşen kümeyi döndürmek için en uygun yolu belirlerler. Sizin yapmanız gereken sadece verimli ve doğru T-SQL kodunu yazmayı öğrenmektir, böylece almak istediğiniz kümeyi doğru şekilde tanımlayabilirsiniz.

Diğer programlama dillerinde bir tecrübeniz olduysa, bu yapının zihniyetini benimsemek biraz zaman alabilir. Bu yazı serisiyle birlikte işlemsel dillerle küme tabanlı declarative T-SQL dili arasındaki boşluğu kapatabilirsiniz.

T-SQL İfade(statement) Türleri

T-SQL ifadeleri üç kategoride düzenlenebilir:

Data Manipulation Language (DML), sorguya ve veriyi editlemeye odaklanmış ifadeler grubudur. Bu yazımızın asıl konusu olan SELECT ile INSERT, UPDATE ve DELETE gibi ifadelerin gerçekleştirdiği işlemlerdir. Bu yazıda SELECT ifadeleri hakkında bilgi edineceğiz.

Data Definition Language (DDL), tablolar, view’lar ve prosedürler gibi veri tabanı nesnelerinin tanımı ve yaşam döngüsünü işleyen T-SQL ifadeler grubudur. CREATE, ALTER ve DROP gibi ifadeleri içermektedir.

Data Control Language (DCL), kullanıcı ve nesneler için güvenlik izinlerini yönetmek için kullanılan T-SQL ifadeleri grubudur. DCL, GRANT, REVOKE ve DENY gibi ifadeleri içermektedir.

T-SQL Dil Bileşenleri

Birçok programlama dili gibi, T-SQL de sorgularda kullanabileceğimiz birçok bileşenler bulunmaktadır. Predicate’ler ile satırları filtreleyebilir, operatörler ile karşılaştırma yapabilir, fonksiyon ve statement’lar ile veriyi manipüle edebilir ya da sistem bilgisine ulaşılabilir ve koda yorum ekleyebilirsiniz. Stored precedur’ler, trigger’lar ve başka nesneler oluşturmak için SELECT ifadeleri ötesinde ifadeler yazmanız gerekirse akış kontrol ifadeleri, değerleri geçici olarak saklamak için değişkenler ve batch operatörleri gibi ögeleri kullanabilirsiniz. Bu ve bir sonraki yazıyla bu söylenenlerin birçoğu ile tanışmış olacağız.

T-SQL Dil Elemanları: Predicate ve Operatörler

T-SQL dilinde mantıksal ifadeler için bir takım unsurlar bulunur. SELECT ifadeleri içerisinde WHERE ve HAVING gibi ifadeler ile filtreler tanımlanabilmektedir. Bu ifadeler, predicate ve operatörler kullanılarak yazılmaktadır.

T-SQL tarafından desteklenen predicate’ler aşağıdaki gibidir:

IN: Bir değerin, listedeki veya alt sorgudaki herhangi bir değerle eşleşip eşleşmediğini bulmak için kullanılır. Örneğin, WHERE day IN (1,5,6,10).
BETWEEN: Bir değer aralığı belirlemek için kullanılır. Örneğin, WHERE rate BETWEEN 3 AND 7.
LIKE: Karakterleri bir patern ile eşleştirmek için kullanılır. Örneğin, WHERE surname LIKE ‘%mith%’ .

Operatörlerin birkaç ortak kategorisi bulunmaktadır:

Comparison: =, <, >, >=, <=, !=, !>, !< ( Bu arada !>, !< ve != ISO standardları arasında yer almaz.)
Logical : AND, OR, NOT.
Arithmetic : +, -, *, /, % (modulo)
Concatenation : Karakter dizelerini birleştirmek için `+`
Assignment : Değer ataması için: `=`

Diğer matematiksel ortamlarda olduğu gibi operatörler burada da öncelik kurallarına tabidir. Aşağıdaki tabloda T-SQL operatörlerinin öncelik sırasını görebilirsiniz:

ÖncelikOperatör
1~ (Bitwise Not)
2/ , * , % (Bölüm, Çarpım, Mod)
3+, -, &, ^, |
(Pozitif/Toplama/Birleştirme, Negatif/Çıkarma, Bitwise AND, Bitwise Exclusive OR, Bitwise OR)
4=, >, <, <=, <, !=, !, !<, !> (Karşılaştırmalar)
5NOT
6AND
7ALL, ANY, BETWEEN, IN, LIKE, OR, SOME
8= (Atama operatörü)

T-SQL Dil Ögeleri: Fonksiyonlar

SQL Server, T-SQL sorguları için birçok seçenek sunmaktadır. Tek değerli sonuç döndüren SYSDATETIME gibi skaler işlevlerden, bu dersin ilerleyen bölümlerinde öğreneceğiniz windowing işlevleri gibi bütün kümeler üzerinde işlem yapabilen ve değer döndürebilenlere kadar uzanmaktadır.

Operatörler gibi, SQL Server fonksiyonları da kategoriler hâlinde düzenlenebilir. Sorgu yazmak için kullanabileceğiniz genel bazı skaler (tek değerli) işlev kategorileri şu şekildedir:

  • String fonksiyonları
    • SUBSTRING, LEFT, RIGHT, LEN, DATALENGTH
    • REPLACE, REPLICATE
    • UPPER, LOWER, RTRIM, LTRIM
    • STUFF
    • SOUNDEX
  • Tarih ve saat fonksiyonları
    • GETDATE, SYSDATETIME, GETUTCDATE
    • DATEADD, DATEDIFF
    • YEAR, MONTH, DAY
    • DATENAME, DATEPART
    • ISDATE
  • Toplama fonksiyonları
    • SUM, MIN, MAX, AVG
    • COUNT, COUNT_BIG
    • STDEV, STDEVP
    • VAR
  • Matematiksel fonksiyonlar
    • RAND, ROUND, POWER, ABS
    • CEILING, FLOOR

T-SQL Dil Ögeleri: Değişkenler

Pek çok programlama dili gibi T-SQL de belirli bir veri tipinin değerini geçici olarak saklayabilme imkanı sunar. Bununla birlikte, diğer programlama ortamlarından farklı olarak, kullanıcı tarafından oluşturulan tüm değişkenler, oluşturulduğu T-SQL batch’i içerisinde lokaldir yani yalnızca o batch içinde görünebilir. SQL Server’da global veya public değişkenleri yoktur.

T-SQL’de bir yerel değişken oluşturmak için isim, veri tipi ve başlangıç değeri verilmelidir. Değişken ismi @ sembolü ile başlamalı, veri türü sistem tarafından atanmış olmalı veya kullanıcı tarafından tanımlanmalıdır. Bu değer kodunuzun çalışacağı veri tabanında kaydedilmiş olmalıdır.

Not: SQL Server literatüründe ve web sitelerinde, @@ ile adlandırılmış “sistem değişkenleri” denen referansları görebilirsiniz (örn. @@ERROR). Bunları sistem fonksiyonları olarak adlandırmak daha doğru olur çünkü kullanıcılar tarafından bu değişkenlere bir değer atanamayabilir.

Bir değişken aynı statement içerisinde adlandırılabilir ve initialize edilebilir. Değişken DECLARE ifadesiyle başlatılmadıysa NULL değerinde oluşturulmaktadır. Daha sonra kendiniz SET ile değişkene bir değer atayabilirsiniz.

Aşağıdaki örnekte ‘Match%’ string değeri atanan bir karakter değişkeni oluşturulmuştur:

DECLARE @search varchar(30) = 'Match%';

Aşağıdaki örnekte bir tarih değişkeni oluşturulur ve değişkene geçerli tarih atanır:

DECLARE @CurrentDate date;
SET @CurrentDate = GETDATE();

Bir değer için kalıcı depolama veya global visibility gerekiyorsa bir tablo oluşturarak içerisinde saklanılabilir. SQL Server, veri tabanlarında hem geçici hem de kalıcı depolama imkanı sağlamaktadır.

T-SQL Dil Ögeleri: İfadeler (statements)

T-SQL, tek bir sonuç döndürmek için SQL Server tarafından çalıştırılan tanımlayıcı, sembol ve operatör kombinasyonlarını sağlar. Bu kombinasyonlara ifadeler denilir ve sorgular için oldukça faydalı ve güçlü bir araçtır. SELECT ifadeleri içerisinde başka ifadeleri şu amaçlarla kullanabilirsiniz:

  • Sütunları çalıştırmak ve manipüle etmek için SELECT içerisinde
  • Mantıksal bir ifadeyle başka bir değerle eşleşen değerleri değiştirmek için CASE içerisinde
  • Satırları filtrelemek için predicate’ler oluşturmak için WHERE içerisinde
  • Tablo ifadeleri şeklinde ileride gerçekleştirilecek işlemler için kullanılan geçici kümelerin oluşturulmasında

İfadeler, skaler bir fonksiyona, sabit bir değere veya değişkenlere bağlı olabilir. Aynı veri türüne sahiplerse veya veri türü daha düşük önceliğinden daha yüksek önceliğe (örneğin, tamsayıdan(int) para birimine(money)) dönüştürülebilirse, operatörler kullanılarak birden fazla ifade birleştirilebilir.

Aşağıdaki örnek, bir sütun üzerinde çalışırken YEAR fonksiyonundan dönen sonucu tarih sütununa ekler:

SELECT YEAR(orderdate) AS currentyear, YEAR(orderdate) + 1 AS nextyear FROM Sales.Orders;

T-SQL Dil Ögeleri: İşlem Akışı, Hatalar ve İşlemlerin Kontrolü

T-SQL, öncelikle bir prosedür dili değil bir veri çekme dili olmasına rağmen yürütme sırasında bir miktar akış kontrolü sağlayan sınırlı bir dizi ifadeyi desteklemektedir.

Yaygın olarak kullanılan akış kontrolü ifadelerinden bazıları şunlardır:

  • IF … ELSE, mantıksal bir teste dayanan branşlama kontrolü sağlamak için.
  • WHILE, koşul true iken bir ifadeyi ya da ifade bloğunu tekrarlamak için.
  • BEGIN … END, bir T-SQL ifadesindeki bloğunun kapsamını tanımlamak için.
  • TRY … CATCH, exception kontrol yapısını tanımlamak için (hata işleme).
  • THROW, bir exception oluşturmak ve çalışmayı CATCH bloğuna yollamak için.
  • BEGIN TRANSACTION, explicit transaction’ın bir parçası olan ifadeler bloğunu işaretlemek için kullanılır. COMMIT TRANSACTION ya da ROLLBACK TRANSACTION ile son bulur.

Akış kontrol operatörleri tek başına sorgularda kullanılamaz. Örneğin, birincil rolünüz bir rapor yazarıysa, bunları kullanmanız gerekmeyebilir. Ancak sorumluluklarınız stored procedure’ler ve trigger’lar gibi nesne oluşturmayı içeriyorsa, bu ögeleri kullanmanız gerekebilir.

T-SQL Dil Ögeleri: Yorum satırları

T-SQL’de, döküman eklemek veya veri tabanı motoruna belirli ifadeleri yok sayması için talimat vermenin iki yolu bulunmaktadır. Hangi yöntemi kullanmanız gerektiği, genellikle göz ardı edilmesini istediğiniz kod satırı sayısına bağlıdır:

  • Tek satır veya çok az sayıdaki kod satırı için, yorum olarak işaretlenecek metnin önüne – – (çift çizgi) koyun. Çizgileri izleyen herhangi bir metin SQL Server tarafından dikkate alınmayacaktır.
  • Daha uzun kod blokları için metninizi / * ve * / karakterleri arasına yerleştirin.

Tek satır yorum satırı örneği:

-- Tek yorum satırı örneği
DECLARE @search varchar(30) = 'Match%'; -- satırın sonu

Blok yorum satırı örneği:

/*
Bu paragraftaki yazının hepsi SQL Server tarafından yorum satırı
olarak işlenecektir.
*/

SQL Server Management Studio’yu (SSMS), Visual Studio® veya SQLCMD gibi birçok sorgu düzenleme aracı, yorumların belirtilmesi için farklı renk kodu kullanır. SSMS’de, renkleri ve yazı tiplerini özelleştirmek için Tools, Options iletişim kutusunu kullanabilirsiniz.

T-SQL Dil Ögeleri: Batch Separators

SSMS gibi SQL Server istemci araçları, veri tabanı motoruna batch adı verilen komutlar gönderir. Bir sorgu editöründeki gibi manuel olarak kod çalıştırıyorsanız, bir metni batch şeklinde göndermeyi seçebilirsiniz. Ayrıca, kodun belirli bölümleri arasına separator(“GO”) eklemeyi de seçebilirsiniz.

Bir batch separator özellikleri müşteri aracınız tarafından ele alınmaktadır. Örneğin, GO anahtar sözcüğü SSMS’deki varsayılan batch ayırıcıdır.

En basit sorgular için batch ayırıcılar kullanılmaz çünkü bir seferde tek bir sorgu gönderilecektir. Ancak nesneler oluşturup üzerlerinde işlem yapmanız gerektiğinde, ifadeleri ayrı gruplara ayırmanız gerekebilir. Örneğin bir CREATE VIEW ifadesi, diğer ifadelerle aynı grupta bulunmayabilir.

Aşağıdaki, aynı gruptaki bir CREATE TABLE ve CREATE VIEW ifadesinin bir örneğidir:

CREATE TABLE table1 (col1 int); CREATE VIEW view1 as SELECT * FROM table1;

Sorgu çalıştırıldığında aşağıdaki hata ortaya çıkacaktır:

Msg 111, Level 15, State 1, Line 2
'CREATE VIEW' must be the first statement in a query batch.

Kullanıcı tarafından oluşturulan değişkenlerin oluşturuldukları batch içerisinde yerel olarak kabul edildiğini belirtmiştik. Bir değişken bir batch içerisinde initialize edilir ve diğer batch içerisinde referansı kullanılırsa ikinci batch çalıştırıldığında işlem başarısız olacaktır. Ortaya çıkan hatayı gidermek için iki CREATE arasına bir GO ayracı eklemek gereklidir.

Mesela aşağıdaki kod, bir batch olarak gönderildiğinde düzgün çalışacaktır:

DECLARE @cust int = 5; SELECT custid, companyname, contactname FROM Sales.Customers WHERE custid = @custid;

Bununla birlikte, değişkenin initialize edildiği ile kullanıldığı sorgu arasına bir GO ayracı eklenirse hata oluşacaktır. Aşağıda bu durum örneklendirilmiştir:

DECLARE @cust int = 5; GO SELECT custid, companyname, contactname FROM Sales.Customers WHERE custid = @custid;

Örnek çalıştırıldığında aşağıdaki hatayı verecektir:

Msg 137, Level 15, State 2, Line 5 Must declare the scalar variable "@custid".

Kaynak:
Operator Precedence
Built-in Functions