ProgramlamaT-SQL Geliştirici / ETL Mühendisi

T-SQL (Transact-SQL) dilinde yinelemeleri ve dallanmayı (döngüler, CASE, GOTO) etkili bir şekilde nasıl uygulayabilirsiniz? Hangi durumlarda bunların kullanımı gerekçelendirilmiştir ve performans için hangi sorunlar vardır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Sorunun geçmişi:
Standart SQL, baştan itibaren klasik programlama unsurları (döngüler, dallanmalar, doğrudan geçiş) olmayan bir deklaratif dil olarak tasarlanmıştır; ancak T-SQL/PLSQL gibi uzantılar ile WHILE, CASE gibi yapılar ve hatta GOTO taklidi gibi yapılar kullanılabilir hale gelmiştir.

Sorun:
Yinelemeli işlemler (tek kayıt üzerinde döngüsel işleme) genellikle, büyük hacimlerin işlenmesinde işin yavaşlamasına neden olur; bunun yerine "set-based" (küme tabanlı) bir yaklaşım benimsenmelidir. Dallanmalar, CASE, IF - çok kullanışlıdır, ancak aşırı iç içe geçme, kodun okunabilirliği ve tahmin edilebilirliğini zedeler.

Çözüm:
Kontrol yapılarının kullanımı, yalnızca toplu (bulk/set) işlemlerle yapılamayacaksa haklı çıkarılmalıdır! Karmaşık hesaplamalar için - küçük bir döngü, tetikleyici veya CASE kabul edilebilir. Toplu işleme için - pencere fonksiyonları veya alt sorgu ile UPDATE kullanmak daha iyidir.

Kod örneği (T-SQL):

DECLARE @i INT = 1 WHILE (@i <= 5) BEGIN IF @i % 2 = 0 PRINT CONCAT('Çift: ', @i) ELSE PRINT CONCAT('Tek: ', @i) SET @i = @i + 1 END

CASE ifadesi:

SELECT num, CASE WHEN num % 2 = 0 THEN 'çift' ELSE 'tek' END AS parity FROM numbers

Anahtar özellikler:

  • Döngü ve dallanmaların, ardışık işlemler için kullanımı gerekçelidir; milyonlarca satır için geçerli değildir.
  • CASE ifadeleri, satır bazında etiketleme için iyi bir şekilde uygundur, ancak toplama/pencere fonksiyonlarının yerini almaz.
  • Çoğu görevde set-based (küme tabanlı) yaklaşım daha karlıdır: tek bir UPDATE veya INSERT.

Kandırıcı sorular.

CASE, WHERE gibi satırları filtrelemek için kullanılabilir mi?

Hayır! CASE farklı değerler döndürüyor, ancak satırları filtrelemiyor. Sık yapılan bir hata - CASE ile filtrelemek yerine WHERE kullanmak, sonuç yanlış olacaktır.

WHILE ile CURSOR arasındaki fark nedir - aynı mı?

WHILE, kullanıcı tarafından yönetilen değişken ile temel bir döngüdür; CURSOR, tablo kayıtları üzerinde çalışır, satır referansı tutar. CURSOR, daha fazla kaynak gerektirir ve genellikle büyük veriler için çok daha yavaş çalışır.

Toplu işleme için hangi yaklaşım daha hızlıdır: WHILE ile UPDATE döngüsü veya bir set-based UPDATE?

%99 durumunda bir set-based UPDATE (veya INSERT) tek başına, bir kayıt üzerinde döngüden çok daha hızlıdır (veya bu "daha esnek" gibi görünse bile).

-- Yanlış yaklaşım DECLARE @id INT = 1 WHILE (@id <= 100000) BEGIN UPDATE t SET flag=1 WHERE id=@id SET @id = @id + 1 END -- Doğru UPDATE t SET flag=1 WHERE id BETWEEN 1 AND 100000

Tipik hatalar ve anti-desainler

  • Toplu işlemler için döngülerin/WHILE kullanımının aşırı olması.
  • İç içe bloklardan çıkmak için GOTO kullanılmakta (program mantığı kaybolur).
  • CASE, değeri dönüştürmek için değil, filtreleme için kullanılır.
  • Birçok iç içe IF... ile mantık "tünelleme".

Hayattan bir örnek

Negatif durum

Bir projede, bir milyon siparişin durumunu güncellemek için her id için bir UPDATE ile döngü yazmışlardı. İşleme ~8 saat sürdü. Yarıda çökme durumunda - her şeyi kaybettiler, manuel olarak düzeltmek zorunda kaldılar.

Artılar:

  • Küçük hacimlerde basit hata ayıklama.

Eksiler:

  • Devasa çalışma süresi.
  • Ölçeklenmesi zor.
  • Arıza durumunda tutarsız durum olma riski fazla.

Pozitif durum

Tek bir ifade ile set-based UPDATE'e geçtirdik. Çalışma süresi 6 dakikaya düştü, işlem atomiktir.

Artılar:

  • Çok daha hızlı.
  • Tüm işlemi basit bir şekilde kontrol etme.
  • Basit bakım.

Eksiler:

  • Her satır için mantığı "özelleştirmek" zor.
  • Ancak döngü kodunda yalnızca yapılan çok "esnek" kontrol sınırlaması vardır.