Stringler, Gerçek Sorguların Yaşadığı Yerdir
Sayılarla iş kolay. Asıl mesele stringlerde başlıyor: başında sonunda boşluk olan isimler, büyük-küçük harfi karışmış e-postalar, tirelerle birbirine yapıştırılmış ID'ler, neredeyse eşleşen ama tam tutmayan serbest metin alanları... SQLite, bunların büyük çoğunluğunu uygulama tarafına hiç dokunmadan halledebileceğin küçük ama derli toplu bir string fonksiyon seti sunuyor.
Bu sayfada en sık ihtiyaç duyacağın sqlite string fonksiyonlarını ele alacağız: birleştirme, parçalama, arama, değiştirme, kırpma ve biçimlendirme.
SQLite'ta String Birleştirme: CONCAT Değil, || Operatörü
SQLite'ta CONCAT fonksiyonu yok. Stringleri birleştirmek için || operatörünü kullanıyoruz:
Sayılar ve diğer veri tipleri otomatik olarak metne dönüştürülür. Ama dikkat edilmesi gereken bir nokta var: Operandlardan herhangi biri NULL olursa, tüm ifade NULL döner. Bu, standart SQL davranışıdır ama çoğu kişiyi şaşırtır:
COALESCE(col, '') veya COALESCE(col, 'default') ile sarmaladığınızda, eksik bir değer yüzünden tüm string'in boşa çıkmasının önüne geçersiniz.
Length, Upper ve Lower
Sürekli elinizin altında olacak üç fonksiyon:
LENGTH, metnin karakter sayısını döndürür, bayt sayısını değil. Eğer gerçekten bayt cinsinden uzunluk lazımsa (nadiren gerekir ama depolama analizi için işe yarar) OCTET_LENGTH kullanmalısınız. UPPER ve LOWER ise varsayılan olarak yalnızca ASCII harfleri dönüştürür; ICU eklentisini yüklemediğiniz sürece aksanlı karakterler olduğu gibi geçer.
SUBSTR: String Parçalama
SUBSTR(text, start, length) bir stringden parça koparmaya yarar. Burada dikkat edilmesi gereken şey: indeksler 1'den başlar — yani ilk karakter 0 değil, 1:
Aklınızda bulunsun:
- Üçüncü argüman opsiyoneldir. Onu vermezseniz,
startkonumundan stringin sonuna kadar her şeyi alırsınız. - Negatif bir
startdeğeri, stringin sonundan itibaren saymaya başlar. startstringin sonunu aşıyorsa, hata almak yerine boş bir string dönersiniz.
Başka bir veritabanından gelen kas hafızanız varsa diye, SUBSTRING de eş anlamlı olarak kabul ediliyor.
INSTR ile Arama: Substring Bulma
INSTR(haystack, needle), needle ifadesinin haystack içindeki ilk geçtiği konumu 1 tabanlı olarak döner; bulamazsa 0 döner:
Yukarıdaki ifade, SQLite'ta "@ işaretinden önceki her şeyi al" demenin klasik yoludur: önce INSTR ile ayraçın yerini bul, ardından SUBSTR ile dilimle. Bu ikiliyi sık sık birlikte kullanacaksınız. Dikkat etmeniz gereken bir nokta var: INSTR eşleşme bulamadığında 0 döner; dolayısıyla dilimleme öncesi bunu kontrol etmek şart. Aksi halde SUBSTR'ye 0 verirsiniz ve sessiz sedasız tuhaf sonuçlar alırsınız.
REPLACE: Bir Alt Dizeyi Başkasıyla Değiştirme
REPLACE(text, old, new) fonksiyonu, old değerinin tüm geçtiği yerleri new ile değiştirir:
Büyük/küçük harfe duyarlıdır ve regex kabul etmez — yalnızca düz bir alt dizgeyle çalışır. Daha karmaşık dönüşümler için REPLACE çağrılarını iç içe geçirebilirsiniz; ama iki üç seviyeyi aştığınız anda işi uygulama tarafında halletmenin zamanı gelmiş demektir.
TRIM, LTRIM, RTRIM
Kullanıcının girdiği veriler genelde başında ve sonunda boşluklarla gelir. TRIM bu boşlukları temizler:
Varsayılan olarak boşlukları kırpar. Hangi karakterlerin temizleneceğini belirtmek için ikinci bir argüman verebilirsiniz — buradaki her karakter, birebir aranan bir alt dize olarak değil, "silinecek karakterler kümesinin" bir üyesi olarak değerlendirilir. Yani TRIM('xxxhelloxx', 'x') sonucu 'hello' döner.
printf: Sayı ve String Biçimlendirme
Sabit ondalık basamak, sıfırla doldurulmuş sayı ya da hex çıktı gibi biçimlendirilmiş bir string'e ihtiyacın olduğunda devreye printf (diğer adıyla format) giriyor:
Format belirteçleri C dilinin geleneğini izler: yani %d, %s, %f, %x, 0 veya boşlukla doldurma gibi tanıdık şeyler. || operatörüyle string birleştirip üstüne bir sürü CAST atmaktan çok daha temiz bir yöntem.
LIKE vs GLOB: Desen eşleştirme farkı
İki operatör, iki ayrı dünya.
LIKE, SQL'in klasik joker karakterlerini kullanır — herhangi bir karakter dizisi için %, tek bir karakter için _ — ve ASCII karakterlerde büyük/küçük harf duyarsızdır:
GLOB, Unix kabuk joker karakterlerini kullanır: herhangi bir karakter dizisi için *, tek bir karakter için ? ve karakter sınıfları için [abc]. Ayrıca büyük/küçük harfe duyarlıdır:
Hangisini ne zaman seçeceğini şöyle düşün: insan tarzı "şununla başlar", "şunu içerir", "şununla biter" eşleştirmeleri için LIKE. Büyük/küçük harf duyarlılığı önemliyse veya karakter sınıflarına ihtiyacın varsa GLOB. İkisi de indeks kullanabilir ama yalnızca desen baştan sabitlenmişse ('foo%', '%foo' değil) — başta joker karakter olduğunda SQLite tüm tabloyu taramak zorunda kalır.
String Bölme: SQLite'ta SPLIT Yok
SQLite, hazır bir SPLIT_STRING fonksiyonuyla gelmiyor. Pratikte kullanabileceğin iki yol var:
Bir sınırlayıcıya göre satırlara bölmek için en temiz yol, JSON dizisi üzerinde json_each kullanmak ya da özyinelemeli (recursive) bir CTE yazmaktır. Bu iki yaklaşımı ilerleyen bölümlerde ele alacağız — şimdilik bilmeniz gereken şu: "bana her kelimeyi ver" SQLite'ta tek satırlık bir iş değil.
Uygulamalı Örnek: İsimleri Temizlemek
Şimdi öğrendiklerimizi birleştirelim. Düşünün ki elinizde bir users tablosu var ve görünen isimler oldukça dağınık: fazladan boşluklar, karışık büyük-küçük harfler, bir de temizlemek istediğiniz "Dr. " veya "Mr. " gibi unvan ön ekleri var:
İfadeyi içten dışa okuyun: önce baştaki/sondaki boşlukları temizleyin, küçük harfe çevirin, unvanları kaldırın ve unvan silindikten sonra başta boşluk kalma ihtimaline karşı bir kez daha TRIM uygulayın. Her adım tek başına basit bir fonksiyon — karmaşıklık, bunları üst üste yığmaktan geliyor. Yığın üç-dört seviyeyi aştığında ya bir generated column'a geçmek (Bölüm: Gelişmiş Özellikler) ya da temizliği veri yükleme sırasında yapmak gerektiğinin işaretidir.
Akılda Kalması Gerekenler
- Birleştirme için
||;NULLsonucu zehirlediği içinCOALESCEkullanın. SUBSTRveINSTRikilisi "bul ve dilimle" senaryolarının çoğunu karşılar.REPLACE, verilen alt dizenin tüm geçtiği yerleri değiştirir.TRIMve akrabaları yalnız boşluk değil, istediğiniz karakter kümesini de temizler.- Biçimli çıktı için doğru araç
printf. - Büyük/küçük harf duyarsız SQL joker karakterleri için
LIKE, shell tarzı ve büyük/küçük harfe duyarlı kalıplar içinGLOB.
Sırada: Sayısal Fonksiyonlar
Stringleri hallettik, doğal duraktaki sıra sayılarda — yuvarlama, mutlak değer, bölme tuhaflıkları ve SQLite'ın son sürümlerde eklediği matematik fonksiyonları. Hepsi bir sonraki sayfada.
Sıkça Sorulan Sorular
SQLite'ta stringler nasıl birleştirilir?
CONCAT yerine || operatörünü kullanın. SQLite'ta varsayılan olarak CONCAT fonksiyonu yoktur — 'Merhaba, ' || isim ifadesi iki metni birleştirip tek bir string döndürür. Dikkat edilmesi gereken nokta şu: operandlardan biri NULL ise sonuç da NULL olur. Bu istediğiniz davranış değilse, null olabilen kolonları COALESCE ile sarmalayın.
SQLite'ta substring (alt metin) nasıl alınır?
SUBSTR(metin, başlangıç, uzunluk) fonksiyonunu kullanın — SUBSTRING olarak da yazılabiliyor. İndeksler 1'den başlar: SUBSTR('merhaba', 1, 3) size 'mer' döndürür. Başlangıç değeri negatif verilirse sondan saymaya başlar. Uzunluk parametresi opsiyoneldir; yazmazsanız belirttiğiniz noktadan sona kadar olan kısmı alır.
SQLite'ta SPLIT_STRING fonksiyonu var mı?
Hayır, SQLite'ta hazır bir split fonksiyonu yok. Çoğu durumda INSTR ve SUBSTR fonksiyonlarını birlikte kullanarak istediğiniz parçayı çekebilirsiniz; ya da bir ayraca göre bölmek için recursive CTE yazabilirsiniz. Sık ihtiyaç duyuyorsanız, JSON dizileri üzerinde çalışan json_each fonksiyonu genellikle elle splitter yazmaktan çok daha temiz bir çözüm olur.
SQLite'ta LIKE ile GLOB arasındaki fark nedir?
LIKE operatörü ASCII için varsayılan olarak büyük/küçük harf duyarsızdır ve joker karakter olarak % ile _ kullanır. GLOB ise büyük/küçük harfe duyarlıdır ve Unix shell tarzı jokerleri (*, ?, [abc]) destekler. Harf duyarlılığı veya karakter sınıfları gerekiyorsa GLOB, klasik SQL tarzı eşleşme yetiyorsa LIKE tercih edilir.