SELECT ... INTO, TROIA'nın SQL'e köprüsü
TROIA'da veritabanından veri çekmenin standart yolu, tanıdık bir SQL SELECT'e çok benziyor ama sonucu doğrudan bir TABLE değişkenine yazan INTO eki ile bitiyor. Tanıdık gelmesine rağmen birkaç önemli fark var — özellikle çok büyük sonuç kümeleriyle çalışırken.
Temel sözdizimi
SELECT [ALL | DISTINCT] {kolonlar}
FROM {tablo} [, {digertablolar}]
[INNER | OUTER JOIN {jointablosu} ON {onkosulu}]
[WHERE {kosul}]
[ORDERBY {kolonlar} [ASC | DESC]]
[INTO {hedeftablo}]
[ROWFETCHSTART {baslangic}]
[ROWFETCHLIMIT {limit}]
[WITHCONTROL {satirsayisi}]
[WITHCACHE]
Küçük ama pratikte kafa karıştırıcı bir detay: TROIA ORDERBY'ı (boşluksuz) bekliyor, ama ORDER BY (boşluklu) de destekleniyor — ikisini karışık kullanan eski koda rastlarsanız şaşırmayın, ikisi de çalışır.
Dinamik SELECT: @ ile çalışma zamanı esnekliği
Bazı ekranlarda hangi kolonların, hangi tablodan, hangi koşulla çekileceği kullanıcı seçimine göre değişir. TROIA bunu @ öneki ile destekliyor:
SELECT @SECILENKOLONLAR
FROM @SECILENTABLO
WHERE @DINAMIKKOSUL
INTO SONUC;
Daha yaygın kullanılan bir alternatif, önceden tanımlı SYSADDITIONALCRITERIA değişkenidir — sabit bir sorguya çalışma zamanında ek koşul eklemek için:
SELECT * FROM SIPARISLER
WHERE CLIENT = SYS_CLIENT @SYSADDITIONALCRITERIA
INTO SONUC;
Dikkat: Select listesinde açık (sabit) ve örtük (@ ile dinamik) kısımları aynı anda kullanamazsınız — belgeler bunu net bir kısıtlama olarak belirtiyor.
Manuel satır satır çekme: SELECTLINE + FETCH
Çok büyük bir sonuç kümesini tek seferde belleğe almak istemediğinizde:
SELECTLINE KULLANICIADI, SIFRE, OLUSTURAN
FROM IASUSERS INTO GECICI;
WHILE 1
BEGIN
FETCH GECICI;
/* SYS_STATUS sıfır olduğu sürece yeni satır geldi demektir */
FETCH, blok halinde çekmeyi de destekliyor: FETCH {tablo} SIZE {satirsayisi}; — bu, milyonlarca satırlı bir tabloyu 1000'erlik gruplar halinde işlemek istediğinizde belleği korumanın yolu.
Veritabanına özgü fonksiyonlar otomatik çevriliyor
CONCAT(), SUBSTRING(), LEFT(), YEAR(), MONTH(), DATEPART(), DATEDIFF(), DATEADD(), LEN() gibi fonksiyonlar, hangi veritabanı motoruna bağlıysanız ona göre otomatik çevriliyor. Örneğin YEAR(OLUSTURULMATARIHI), PostgreSQL'de arka planda CAST(EXTRACT(YEAR FROM OLUSTURULMATARIHI) AS INTEGER)'a dönüşüyor. Bu, troia-platformu-nasil-calisir yazısında bahsettiğim "veritabanı bağımsızlığı" vaadinin somut karşılığı — ama bu fonksiyon listesinin dışına çıkıp veritabanına özgü bir SQL fonksiyonu yazarsanız (örneğin MSSQL'e özgü bir sistem fonksiyonu), taşınabilirlik garantisi orada biter.
WITHCACHE: dikkatli kullanılması gereken bir kısayol
WITHCACHE, aynı sorgunun tek bir oturum/kullanıcı etkileşimi içinde tekrarlanmasını önlemek için sonucu önbelleğe alıyor. Belgeler bunu uzun vadeli bir çözüm olarak önermiyor — önbellek, EnableDBSelectionCache sunucu ayarıyla global olarak kapatılabiliyor, yani bir ekranın WITHCACHE'e bel bağlaması, o sunucu ayarı değiştiğinde sessizce farklı davranmaya başlayabilir.
Gerçek bir örnek: sayfalama ile büyük bir listeyi çekmek
/* Sipariş listesini sayfalama ile çeker, tek seferde tüm tabloyu belleğe almaz. */
PARAMETERS:
INTEGER SAYFANO,
INTEGER SAYFABOYUTU;
LOCAL:
TABLE SIPARISLER(ID INTEGER, MUSTERIADI CHAR(100), TUTAR DECIMAL);
INTEGER BASLANGIC;
BASLANGIC = (SAYFANO - 1) * SAYFABOYUTU;
SELECT ID, MUSTERIADI, TUTAR FROM SIPARIS_KARTI
ORDERBY TARIH DESC
ROWFETCHSTART BASLANGIC
ROWFETCHLIMIT SAYFABOYUTU
INTO SIPARISLER;
RETURN SIPARISLER;
Sık yapılan hatalar
ROWFETCHLIMITkullanmadan tüm tabloyu çekip TROIA tarafında sayfalamaya çalışmak — büyük tablolarda bu, veritabanının kendi sayfalama yeteneğini (ve dizinlerini) hiç kullanmadan tüm veriyi application server belleğine taşımak demek; performans farkı ciddi olabilir.WITHCACHE'i "her zaman güvenli bir hızlandırma" sanmak — önbellek başka bir kullanıcının/işlemin veriyi değiştirdiği ama sizin hâlâ eski sonucu gördüğünüz senaryolara yol açabilir; sık değişen veri için kullanmayın.- Veritabanına özgü, listede olmayan bir fonksiyonu doğrudan yazmak — MSSQL'de test edip PostgreSQL'de aynı kodu çalıştırdığınızda "fonksiyon tanınmıyor" hatası almak, tam olarak bu yüzden olur; belgelenmiş fonksiyon setine sadık kalmak taşınabilirliği korur.
SELECTLINE/FETCHsonrası döngüyü doğru koşulla bitirmemek —SYS_STATUSkontrolünü atlayıp sabit bir sayaçla döngüyü sınırlamaya çalışmak, ya eksik veri okumaya ya da sonsuz döngüye yol açabilir.
Sıradaki adım
Bir sonraki yazıda, tekrar eden alan tanımlarını (uzunluk, formatlama, zoom davranışı) tek bir yerden yönetmeyi sağlayan Domain kavramına değineceğim.
Yorumlar (0)
Yorum Yaz