SQL sunucusu bir where ifadesindeki durumu yoksay


91

"Where" deyiminin büyük / küçük harf duyarlı olmadığı bir SQL sorgusu (MS SQL Sunucusu) nasıl oluşturabilirim?

SELECT * FROM myTable WHERE myField = 'sOmeVal'

Vakayı görmezden gelerek sonuçların geri gelmesini istiyorum

Yanıtlar:


137

Bir SQL Server veritabanının varsayılan yapılandırmasında, dize karşılaştırmaları büyük / küçük harfe duyarlı değildir. Veritabanınız bu ayarı geçersiz kılarsa (alternatif bir harmanlama kullanarak), sorgunuzda ne tür harmanlama kullanacağınızı belirtmeniz gerekir.

SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS

Sağladığım harmanlamanın sadece bir örnek olduğunu unutmayın (yine de sizin için büyük olasılıkla gayet iyi çalışacaktır). SQL Server harmanlamalarının daha kapsamlı bir taslağı burada bulunabilir .


Sadece onaylamak için, bunun sadece WHEREifadenin sonuna bir kez eklenmesi gerekiyor ve tüm WHEREmaddeleri etkileyecek , değil mi?
ashleedawg

Cevabınızın bir sütun değerini UPPERveya büyük / LOWERküçük harfe dönüştürerek daha sonra LIKEarama yapmak için kullanarak herhangi bir performans sorunu olup olmadığını bilmek ister misiniz?
Shaiju T

1
@ashleedawg - güzel soru .. satır başına bir ayar gibi görünüyor.
Leo Gurdian

30

Genellikle dize karşılaştırmaları büyük / küçük harfe duyarlı değildir. Veritabanınız büyük / küçük harfe duyarlı harmanlama için yapılandırılmışsa, büyük / küçük harfe duyarlı olmayan bir tane kullanmaya zorlamanız gerekir:

SELECT balance FROM people WHERE email = 'billg@microsoft.com'
  COLLATE SQL_Latin1_General_CP1_CI_AS 

@AskeB. ve Andrejs: Bu teknik olarak bir veritabanı yapılandırma sorunu değildir. Bakınız Cevabımı dize karşılaştırmaları üzerine açıklama.
Solomon Rutzky

21

Başka bir yerde başka bir çözüm buldum; yani kullanmak

upper(@yourString)

ama buradaki herkes, SQL Server'da bunun önemli olmadığını çünkü durumu görmezden geliyor? Veritabanımızın büyük / küçük harfe duyarlı olduğundan oldukça eminim.


7
Bir veritabanının büyük / küçük harfe duyarlı hale getirilebileceği konusunda haklısınız, ancak bu, gerekli olsa bile oldukça verimsizdir. COLLATE, kullanılacak anahtar kelimedir.
mjaggard

1
Konuyu açtığın için teşekkürler @mjaggard. Umarım siz veya cevabımı olumsuz oylayan herhangi biri, benim gibi cevapları arayan ve bulan benim gibi herkesin iyiliği için ayrıntıya girersiniz.
Danny

1
Tamamen mantıklı bir açıklama olduğu için buna olumlu oy verdi. Çok fazla ek yükü harmanlayın ve dizenizde harmanlamanın anlamadığı karakterler varsa? Latin 1 berbat bir kodlama şemasıdır. Dizinizde kesme işareti varsa anlamlı sonuçlar elde etmede bol şans (Like: O'Brien).
eggmatters

2
Ayrıca oy verildi. Bunun yararlı olacağı birçok durum düşünebiliyorum. Ek olarak, genellikle bir şeyi yapmanın birden fazla iyi yolu vardır.
Inversus

1
Karşılaştırma amacıyla dizge durumunu değiştirmek genellikle kötüdür. Bazı dillerde, dönüşümler gidiş-dönüş değildir. yani DÜŞÜK (x)! = DÜŞÜK (ÜST (x)).
Ceisc

17

En iyi 2 cevap ( Adam Robinson ve Andrejs Cainikovs'tan ) teknik olarak işe yaradıkları için biraz doğru, ancak açıklamaları yanlış ve bu nedenle birçok durumda yanıltıcı olabilir. Örneğin, SQL_Latin1_General_CP1_CI_ASharmanlama birçok durumda işe yarayacak olsa da, büyük / küçük harfe duyarlı olmayan uygun harmanlama olduğu varsayılmamalıdır. Aslında, OP'nin büyük / küçük harfe duyarlı (veya muhtemelen ikili) harmanlama ile bir veritabanında çalıştığı göz önüne alındığında, OP'nin pek çok kurulum için varsayılan harmanlamayı kullanmadığını biliyoruz (özellikle bir işletim sistemi ABD İngilizcesi dili gibi) kullanarak: SQL_Latin1_General_CP1_CI_AS. Elbette, OP kullanıyor olabilirSQL_Latin1_General_CP1_CS_AS , ancakVARCHARveri kaybına neden olabileceğinden ve harmanlamanın yerel ayarı / kültürü tarafından kontrol edildiği için kod sayfasını değiştirmemek önemlidir (yani Latin1_General - Fransızca - İbranice vb.). Lütfen aşağıdaki 9. maddeye bakın.

Diğer dört cevap farklı derecelerde yanlıştır.

Okuyucuların umarız en uygun / verimli seçimleri yapabilmeleri için buradaki tüm yanlış anlamaları açıklığa kavuşturacağım.

  1. Kullanmayın UPPER(). Bu tamamen gereksiz fazladan iştir. Bir COLLATEcümle kullanın . Her iki durumda da bir dize karşılaştırmasının yapılması gerekir, ancak kullanılması UPPER()aynı zamanda büyük harf eşlemesinin olup olmadığını görmek için karakter karakter de kontrol etmeli ve sonra değiştirmelidir. Ve bunu her iki tarafta da yapmanız gerekiyor. Ekleme COLLATE, işlemi varsayılan olarak yapacağından farklı bir kurallar kümesi kullanarak sıralama anahtarlarını oluşturmaya yönlendirir. Bu test komut dosyasında (PasteBin'de) kanıtlandığı COLLATEgibi kullanmak , kullanmaktan kesinlikle daha etkilidir (veya bu kelimeyi seviyorsanız "performans" ) .UPPER()

    @Ceisc tarafından @ Danny'nin cevabında not edilen sorun da var:

    Bazı dillerde, dönüşümler gidiş-dönüş değildir. yani DÜŞÜK (x)! = DÜŞÜK (ÜST (x)).

    Türkçe büyük harf "İ" ortak bir örnektir.

  2. Hayır, harmanlama, en azından bu bağlamda veritabanı çapında bir ayar değildir. Veritabanı düzeyinde bir varsayılan harmanlama vardır ve bu, COLLATEcümleyi belirtmeyen değiştirilmiş ve yeni oluşturulmuş sütunlar için varsayılan olarak kullanılır (muhtemelen bu yaygın yanlış anlamanın geldiği yerdir), ancak siz olmadığınız sürece sorguları doğrudan etkilemez. dize değişmezlerini ve değişkenlerini diğer dize değişmezleri ve değişkenleriyle karşılaştırma veya veritabanı düzeyinde meta verileri referans veriyorsunuz.

  3. Hayır, harmanlama sorgu başına değildir.

  4. Harmanlamalar, sorgu başına değil, yüklem (yani işlenen bir şey) veya ifade başınadır. Ve bu sadece WHEREcümle için değil, tüm sorgu için geçerlidir . Bu, JOIN, GROUP BY, ORDER BY, PARTITION BY, vb. Kapsar.

  5. Hayır, aşağıdaki nedenlerden ötürü VARBINARY(örn. convert(varbinary, myField) = convert(varbinary, 'sOmeVal')) 'E dönüştürmeyin :

    1. bu, büyük / küçük harfe duyarlı olmayan ikili bir karşılaştırmadır (bu sorunun sorduğu da budur)
    2. ikili karşılaştırma yapmak istiyorsanız, ikili harmanlama kullanın. _BIN2SQL Server 2008 veya daha yenisini kullanıyorsanız ile biten birini kullanın, aksi takdirde ile biten birini kullanmaktan başka seçeneğiniz yoktur _BIN. Verilerse, NVARCHARo zaman hangi yerel ayarı kullandığınız önemli değildir, çünkü bu durumda hepsi aynıdır, bu nedenle Latin1_General_100_BIN2her zaman işe yarar . Veri ise VARCHAR, veri (örneğin şu anda aynı yerel kullanmalıdır Latin1_General, French, Japanese_XJISyerel kullanılan kod sayfasını belirler ve kod sayfalarını değişen verileri (yani veri kaybı) değiştirebilir çünkü, vs).
    3. boyutu belirtmeden değişken uzunluklu bir veri türü kullanmak varsayılan boyuta bağlı olacaktır ve veri türünün kullanıldığı bağlama bağlı olarak iki farklı varsayılan vardır. Dize türleri için 1 veya 30'dur. Onunla birlikte kullanıldığında CONVERT()30 varsayılan değeri kullanacaktır. Tehlike, dizge 30 bayttan fazla olabilirse, sessizce kesilecek ve muhtemelen bu yüklemden yanlış sonuçlar alacaksınız.
    4. Büyük / küçük harfe duyarlı bir karşılaştırma isteseniz bile, ikili harmanlamalar büyük / küçük harfe duyarlı değildir (başka bir çok yaygın yanlış anlama).
  6. Hayır, LIKEher zaman büyük / küçük harfe duyarlı değildir. Başvurulan sütunun harmanlamasını veya bir değişken bir değişmez dize ile karşılaştırılırsa veritabanının harmanlamasını veya isteğe bağlı COLLATEcümle ile belirtilen harmanlamayı kullanır .

  7. LCASEbir SQL Server işlevi değildir. Oracle veya MySQL gibi görünüyor. Veya muhtemelen Visual Basic?

  8. Sorunun bağlamı, bir sütunu bir dizge ile karşılaştırdığı için, ne örneğin harmanlaması (genellikle "sunucu" olarak adlandırılır) ne de veritabanının harmanlaması burada herhangi bir doğrudan etkiye sahip değildir . Harmanlamalar her sütun için saklanır ve her sütun farklı bir harmanlamaya sahip olabilir ve bu harmanlamaların veritabanının varsayılan harmanlaması veya örneğin harmanlamasıyla aynı olması gerekmez. Elbette, örnek harmanlama, yeni oluşturulan bir veritabanının, veritabanı oluşturulurken COLLATEyan tümce belirtilmemişse varsayılan harmanlama olarak kullanacağı şey için varsayılan değerdir . Ve benzer şekilde, veritabanının varsayılan harmanlaması, değiştirilmiş veya yeni oluşturulan bir sütunun, COLLATEmadde belirtilmemişse kullanacağı şeydir .

  9. Aksi takdirde sütunun harmanlamasıyla aynı olan, büyük / küçük harfe duyarlı olmayan harmanlamayı kullanmalısınız. Sütunun harmanlamasını bulmak için aşağıdaki sorguyu kullanın (tablonun adını ve şema adını değiştirin):

    SELECT col.*
    FROM   sys.columns col
    WHERE  col.[object_id] = OBJECT_ID(N'dbo.TableName')
    AND    col.[collation_name] IS NOT NULL;
    

    Sonra sadece değiştirmek _CSolmak _CI. Böylece Latin1_General_100_CS_ASolur Latin1_General_100_CI_AS.

    Sütun ikili harmanlama kullanıyorsa ( _BINveya ile biten _BIN2), aşağıdaki sorguyu kullanarak benzer bir harmanlama bulun:

    SELECT *
    FROM   sys.fn_helpcollations() col
    WHERE  col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
    

    Örneğin, sütunun kullandığını varsayarsak, şunu yapın Japanese_XJIS_100_BIN2:

    SELECT *
    FROM   sys.fn_helpcollations() col
    WHERE  col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
    

Harmanlamalar, kodlamalar vb. Hakkında daha fazla bilgi için lütfen şu adresi ziyaret edin: Harmanlama Bilgileri


7

Hayır, sadece kullanmak LIKEişe yaramayacaktır. LIKEVerdiğiniz kalıpla tam olarak eşleşen değerleri arar. Bu durumda LIKE, "someval" değil, yalnızca "sOmeVal" metni bulunur.

Pratik bir çözüm işlevi kullanıyor LCASE(). LCASE('sOmeVal')metninizin küçük harfli dizesini alır: 'someval'. Karşılaştırmanızın her iki tarafı için bu işlevi kullanırsanız, çalışır:

SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')

İfade, iki küçük harf dizgisini karşılaştırır, böylece 'sOmeVal' değeriniz diğer tüm 'someval' gösterimleriyle eşleşir (örn. 'Someval', 'sOMEVAl' vb.).


7
_CI harmanlanmış SQL Server kurulumlarının% 99,9'unda LIKE, Büyük / Küçük Harfe Duyarlı değildir.
RichardTheKiwi

1
Günümüzde işlevin adı LOWER
David Brossard

@DavidBrossard ve David Hermanns, LCASE()SQL Server'da olduğunu sanmıyorum (en azından görebildiğim kadarıyla). Bu cevabın tamamen farklı bir RDBMS için olduğunu düşünüyorum. Bakınız Cevabımı dize karşılaştırmaları üzerine açıklama.
Solomon Rutzky

4

Büyük / küçük harfe duyarlı olanı böyle bir değişken ikilisine çevirerek zorlayabilirsiniz:

SELECT * FROM myTable 
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')

3
Bu işlevsel olsa da, tavsiye edilen bir yaklaşım değildir. Sıralama ve dize karşılaştırmalarını yönetmek için harmanlamalar vardır.
Adam Robinson

@AdamRobinson bu konu "dizi karşılaştırmaları" değil mi?
Fandango68

@ Fandango68 Evet, öyle ve Adam dize karşılaştırmaları yaparken harmanlamaların daha iyi olduğunu söylüyor.
JLRishe

@ Fandango68 Bu yanıt birkaç düzeyde yanlış. Bakınız Cevabımı özellikle 5. işaret detaylar için
Solomon Rutzky

@AdamRobinson bakınız cevabım dize karşılaştırmaları üzerine açıklama.
Solomon Rutzky

2

Hangi veritabanındasın? MS SQL Server ile bu, veritabanı çapında bir ayardır veya COLLATE anahtar sözcüğüyle sorgu başına bunu geçersiz kılabilirsiniz.


Merhaba. SQL Server için, bu sorunun ne hakkında olduğu açısından, bu ne veritabanı çapında ne de sorgu başına bir ayardır. Bakınız Cevabımı detayları için.
Solomon Rutzky
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.