PostgreSQL: “Büyük / küçük harfe duyarsız” sorgu nasıl yapılır


339

PostgreSQL'de büyük-küçük harf duyarsız sorgular yazmak için herhangi bir yolu var mı, eg Aşağıdaki 3 sorgu aynı sonucu döndürmek istiyorum.

SELECT id FROM groups where name='administrator'

SELECT id FROM groups where name='ADMINISTRATOR'

SELECT id FROM groups where name='Administrator'

citext Postgres kurulumunuzla birlikte geliyorsa, citext tipini deneyin. Büyük / küçük harfe duyarsız metin
Michael Buen

2
Bu soruya yeni başlayanlar için, resmi postgres belgelerine olan bu bağlantı , burada verilen tüm cevapları ve diğer birkaç seçeneği içerir.
Part Atışı

Efendim @Arun tarafından verilen yanıta kabul edilen cevabı yeniden atayın lütfen. Çok daha az karmaşıktır ve uyguladıktan sonra bir sürü sıkıntı çekmez.
zeliboba

Yanıtlar:


451

Karşılaştırmadan önce dizeleri küçük harfe dönüştürmek için DÜŞÜK işlevini kullanın .

Bunu dene:

SELECT id 
  FROM groups
 WHERE LOWER(name)=LOWER('Administrator')

92
Yüklemeli sütunlarda DÜŞÜK (veya herhangi bir işlev) kullanmanın - bu durumda "ad" - herhangi bir dizinin artık aranmaya neden olmayacağına dikkat etmek önemlidir. Bu büyük veya sık sorulan bir tablo ise, soruna neden olabilir. Büyük / küçük harfe duyarlı olmayan harmanlama, citext veya işleve dayalı bir dizin performansı artırır.
Ürdün

108
Veya sadece böyle bir dizin oluşturun: CREATE INDEX idx_groups_name ON gruplar alt (ad);
Daniel

19
Ayrıca varchar_pattern_opsdizinin LIKE 'xxx%'sorgu ile çalışmasını isteyip istemediğinizi belirtin , ör CREATE INDEX ix_groups_name ON groups (lower(name) varchar_pattern_ops).
sayap

10
ILIKE operatörünün kullanılması (aşağıdaki diğer cevaplarda gösterildiği gibi), en çok oylanan cevap olmasına rağmen daha basit bir yaklaşımdır.
Ryan

5
Buradaki yorumları gözden geçirerek, burada birçok öneri öneriliyor ILIKE, Çalışacak but with slow response,. Hesaplamaların sonuçlarına dayalı olarak tablolara hızlı erişim elde etmek için, bunu kontrol eden herkesin kabul edilen cevapla gitmesi gerektiğini öneririm. Burada ve burada
Afolabi Olaoluwa Akinwumi

231

ILIKEyerine kullanmakLIKE

SELECT id FROM groups WHERE name ILIKE 'Administrator'

1
ILIKESpring Boot'da kullanıldığında Hazırda Bekletme tarafından desteklenmediğini unutmayın .
AnT

@ org.hibernate.dialect.PostgreSQL94DialectVe Spring Boot 2.0.6 ile çalışır . Ancak IntelliJ bundan şikayetçi.
Samintha Kaveesh

134

En yaygın yaklaşım, arama dizesini ve verileri küçük veya büyük harf olarak belirlemektir. Ancak bununla ilgili iki sorun var.

  1. İngilizce çalışır, ancak tüm dillerde çalışmaz. (Çoğu dilde bile olmayabilir.) Her küçük harf karşılık gelen bir büyük harf içermez; her büyük harf karşılık gelen küçük harf içermez.
  2. Lower () ve upper () gibi işlevleri kullanmak size sıralı bir tarama sağlar. Dizin kullanamaz. Test sistemimde, less () kullanmak, dizin kullanabilen bir sorgudan yaklaşık 2000 kat daha uzun sürer. (Test verilerinin 100 binden fazla satırı vardır.)

Daha etkili olabilecek en az üç daha az kullanılan çözüm vardır.

  1. Büyük / küçük harf duyarsız bir veri türünün davranışını taklit eden citext modülünü kullanın . Bu modülü yükledikten sonra, büyük / küçük harfe duyarlı olmayan bir dizin oluşturabilirsiniz CREATE INDEX ON groups (name::citext);. (Ama aşağıya bakınız.)
  2. Büyük / küçük harfe duyarlı olmayan bir harmanlama kullanın. Bu, bir veritabanı başlattığınızda ayarlanır. Büyük / küçük harfe duyarlı olmayan bir harmanlama kullanmak, istemci kodundan hemen hemen her formatı kabul edebileceğiniz anlamına gelir ve yine de faydalı sonuçlar döndürürsünüz. (Ayrıca büyük / küçük harfe duyarlı sorgular yapamayacağınız anlamına gelir.
  3. İşlevsel bir dizin oluşturun. Düğmesini kullanarak küçük harfli bir dizin oluşturun CREATE INDEX ON groups (LOWER(name));. Sorgular gibi olan dizine yararlanabilir, Bunu yaptıktan sonra SELECT id FROM groups WHERE LOWER(name) = LOWER('ADMINISTRATOR');, ya SELECT id FROM groups WHERE LOWER(name) = 'administrator';Yapmalisin hatırlamıyorum gerçi, düşük () kullanmak.

Citext modülü, büyük / küçük harfe duyarlı olmayan bir veri türü sağlamaz. Bunun yerine, her bir dize küçük harfli gibi davranır. Yani, lower()yukarıdaki 3 numaralı gibi her bir dizgeyi çağırmışsınız gibi davranır . Avantajı, programcıların küçük harf dizilerini hatırlamak zorunda olmamalarıdır. Ancak, citext kullanmaya karar vermeden önce dokümanlardaki "Dize Karşılaştırma Davranışı" ve "Sınırlamalar" bölümlerini okumanız gerekir.


1
# 1 hakkında: Bir sorun olmamalı, çünkü iki farklı dize olurdu (bunu yapmak gibi düşünün col = 'a've col = 'b'). Hakkında # 2: Dediğiniz gibi, bir ifade üzerinde bir dizin oluşturabilirsiniz, bu yüzden bu gerçekten bir sorun değildir. Ancak, harmanlamayı değiştirmenin büyük olasılıkla en iyi çözüm olduğunu kabul ediyorum.
Vincent Savard

5
Birisi bana PostgreSQL yerleşik harmanlamalarının büyük / küçük harfe duyarlı olmayan harmanlamalarını söyleyebilir mi? Ben bir seçenek olarak görüyorum ama net Postgres için büyük / küçük harf duyarsız bir harmanlama hakkında bir şey bulamıyor musunuz?
khorvat

1
@AnupShah: Hayır, bunu söylemiyorum. Windows'ta PostgreSQL çalıştırmıyorum. 9.4 dokümanı şöyle der : "Tüm platformlarda, default, C ve POSIX adlı harmanlamalar kullanılabilir. İşletim sistemi desteğine bağlı olarak ek harmanlamalar da olabilir." Hangi PostgreSQL düşüncelerinin mevcut olduğunu görebilirsiniz select * from pg_collation;.
Mike Sherrill 'Cat Recall'

1
@Matthieu: Bu, bildiğim konuya en iyi giriş (ve dikkat): Akılda Tutulması Gereken Edge Cases. Bölüm 1 - Metin .
Mike Sherrill 'Cat Recall'


95

Kullanabilirsiniz ILIKE. yani

SELECT id FROM groups where name ILIKE 'administrator'

Benim için doğru ve iyi çalışıyor, MAC OS X (Dağ Aslanı) kullanıyorum.
ADJ

5
Bu işe yarayacak, ancak yavaş yanıt verecek. Hesaplamaların sonuçlarına dayalı olarak tablolara hızlı erişim elde etmek için, bu lowerişlevi kullanmanızı öneririm . Daha fazla ayrıntı
Afolabi Olaoluwa Akinwumi

1
@AfolabiOlaoluwaAkinwumi temel olarak bu, bilinen değerleri filtrelemeye karşı sonuçları aradığınızdan mı kaynaklanır? İkinci durumda, eşitlik operatörünün çalışmasını sağlayan veri düzeyinde tek bir muntazam durum devam ettirilmelidir. [Kişisel tavsiye, tip kodu değerleri için üst pascal durumdur]
Chris Marisic

53

Ayrıca ILIKEanahtar kelimeyi okuyabilirsiniz . SQL standardına uymasa da, bazen oldukça yararlı olabilir. Daha fazla bilgi için buraya bakın: http://www.postgresql.org/docs/9.2/static/functions-matching.html


9
Burada dikkat edilmesi gereken bir şey kötü niyetli kullanıcı girdisidir. Gibi bir sorgu çalıştırırsanız email ILIKE 'user-input-email-here', kullanıcı girişinden kaçtığınızdan emin olun. Aksi takdirde, kullanıcılar% gibi bir şeyle eşleşen karakterler girebilir.
Matt De Leon

2
@MattDeLeon Merhaba. İyi dedi. Ama sadece sormak istiyorum, eğer kullanırsam ILIKEve prepared statementsbu beni koruyacak mı sql injection?
slevin

Emin değilim, hazırlanan ifadeye bir kaçış dizesi göndermek istiyorsunuz.
Matt De Leon

1
"ILIKE anahtar sözcüğü, LIKE yerine etkin yerel ayara göre büyük / küçük harf duyarsız hale getirmek için kullanılabilir. Bu, SQL standardında değildir, ancak bir PostgreSQL uzantısıdır." 9.3'te cazibe gibi çalışıyor
Aleksey Deryagin

1
ILIKE daha yavaştır lower(column_name) like %expression%.
Patryk Imosa

28

POSIX gibi normal ifadeleri de kullanabilirsiniz.

SELECT id FROM groups where name ~* 'administrator'

SELECT 'asd' ~* 'AsD' İadeler t


1
Aynı sorunu yaşadım, PostgreSQL veritabanımda büyük / küçük harfe duyarlı olmayan aramalara ihtiyacım vardı. Kullanıcı giriş dizesini normal bir ifadeye dönüştürmeyi düşündüm. Şimdi, = veya LIKE yerine ~ * kullanmak mükemmel çalıştı! Yeni dizinler, sütunlar veya başka bir şey oluşturmam gerekmiyordu. Elbette, normal ifade arama düz bayt karşılaştırmasından daha yavaştır, ancak performans üzerindeki etkinin iki veri kümesini işlemek zorunda kalmadan çok daha büyük olacağını düşünmüyorum (sadece arama için bir alt veya üst harf, daha sonra ilgili orijinali almak zorundayım) diğer kümedeki veriler). Ayrıca, bu daha temiz!
Cyberknight

1
Güzel, ancak regexp_matches () ile nasıl yapılır?
WKT

Postgres belgelerine göre: ~~ operatörü LIKE'ye eşittir ve ~~ * ILIKE'ye karşılık gelir. Sırasıyla NOT GİBİ DEĞİL ve İLK GİBİ temsil etmeyen! ~~ ve! ~~ * operatörleri de vardır. Bu operatörlerin tümü PostgreSQL'e özeldir.
sh4

Metinde parantez bulunduğunda bir sorunla karşılaştım, çalışmıyor. gibi: "kod (LC)"
Oshan Wisumperuma

8

Kullanılması ~*INSTR işlevselliği ile, büyük ölçüde performansa artırabilir.

SELECT id FROM groups WHERE name ~* 'adm'

VEYA içeren ad içeren satırları döndürmek 'adm'.


1
Hey, Robin, SO'ya hoş geldin. James Brown'ın cevabı zaten bu çözümü önerdi. Ayrıca, önerilen cevabınız hiçbir şekilde normal ifadeden faydalanmamaktadır.
Rafael
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.