Bagaimana cara membuat kueri SQL (MS SQL Server) di mana klausa "di mana" tidak peka huruf besar / kecil?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Saya ingin hasilnya kembali dengan mengabaikan kasus ini
sql
sql-server
where-clause
case-insensitive
Raul Agrait
sumber
sumber
WHERE
pernyataan, dan akan memengaruhi semuaWHERE
klausa, bukan?UPPER
atauLOWER
kapitalisasi lalu menggunakanLIKE
untuk mencari?Biasanya, perbandingan string tidak peka huruf besar / kecil. Jika database Anda dikonfigurasi untuk pemeriksaan case-sensitive, Anda perlu memaksa untuk menggunakan case tidak sensitif:
SELECT balance FROM people WHERE email = '[email protected]' COLLATE SQL_Latin1_General_CP1_CI_AS
sumber
Saya menemukan solusi lain di tempat lain; yaitu, untuk digunakan
tetapi semua orang di sini mengatakan bahwa, di SQL Server, tidak masalah karena tetap mengabaikan kasus? Saya cukup yakin database kita peka huruf besar kecil.
sumber
2 jawaban teratas (dari Adam Robinson dan Andrejs Cainikovs ) agak, agak benar, karena secara teknis berhasil, tetapi penjelasan mereka salah dan bisa menyesatkan dalam banyak kasus. Misalnya, meskipun
SQL_Latin1_General_CP1_CI_AS
pemeriksaan akan berfungsi dalam banyak kasus, pemeriksaan tersebut tidak boleh dianggap sebagai pemeriksaan tidak peka huruf besar / kecil. Faktanya, mengingat bahwa OP bekerja dalam database dengan pemeriksaan case-sensitive (atau mungkin biner), kita tahu bahwa OP tidak menggunakan pemeriksaan yang merupakan default untuk begitu banyak instalasi (terutama yang diinstal pada OS. menggunakan bahasa Inggris AS sebagai bahasa):SQL_Latin1_General_CP1_CI_AS
. Tentu, OP bisa digunakanSQL_Latin1_General_CP1_CS_AS
, tapi saat bekerja denganVARCHAR
data, penting untuk tidak mengubah halaman kode karena dapat menyebabkan hilangnya data, dan itu dikontrol oleh lokal / budaya pemeriksaan (yaitu Latin1_General vs Perancis vs Ibrani dll). Silakan lihat poin # 9 di bawah.Empat jawaban lainnya salah dalam berbagai tingkatan.
Saya akan mengklarifikasi semua kesalahpahaman di sini sehingga pembaca dapat membuat pilihan yang paling tepat / efisien.
Jangan gunakan
UPPER()
. Itu benar-benar pekerjaan ekstra yang tidak perlu. GunakanCOLLATE
klausa. Perbandingan string perlu dilakukan dalam kedua kasus, tetapi menggunakanUPPER()
juga harus memeriksa, karakter demi karakter, untuk melihat apakah ada pemetaan huruf besar, dan kemudian mengubahnya. Dan Anda perlu melakukan ini di kedua sisi. MenambahkanCOLLATE
hanya mengarahkan pemrosesan untuk menghasilkan kunci sortir menggunakan sekumpulan aturan yang berbeda dari yang akan dilakukan secara default. MenggunakanCOLLATE
pasti lebih efisien (atau "performant", jika Anda suka kata itu :) daripada menggunakanUPPER()
, sebagaimana dibuktikan dalam skrip pengujian ini (di PasteBin) .Ada juga masalah yang dicatat oleh @Ceisc pada jawaban @ Danny:
Huruf besar Turki "İ" adalah contoh yang umum.
Tidak, pemeriksaan bukanlah pengaturan seluruh database, setidaknya tidak dalam konteks ini. Ada pemeriksaan default tingkat database, dan digunakan sebagai default untuk kolom yang diubah dan yang baru dibuat yang tidak menentukan
COLLATE
klausa (yang mungkin berasal dari kesalahpahaman umum ini), tetapi tidak memengaruhi kueri secara langsung kecuali Anda adalah membandingkan literal string dan variabel dengan literal dan variabel string lain, atau Anda mereferensikan meta-data tingkat database.Tidak, pemeriksaan tidak dilakukan per kueri.
Collations adalah per predikat (yaitu sesuatu operan sesuatu) atau ekspresi, bukan per query. Dan ini berlaku untuk seluruh kueri, bukan hanya
WHERE
klausa. Ini mencakup JOIN, GROUP BY, ORDER BY, PARTITION BY, dll.Tidak, jangan ubah ke
VARBINARY
(mis.convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
) Karena alasan berikut:_BIN2
jika Anda menggunakan SQL Server 2008 atau yang lebih baru, jika tidak, Anda tidak punya pilihan selain menggunakan yang diakhiri dengan_BIN
. Jika datanyaNVARCHAR
maka tidak masalah lokal mana yang Anda gunakan karena semuanya sama dalam kasus itu, karenanyaLatin1_General_100_BIN2
selalu berfungsi. Jika dataVARCHAR
, Anda harus menggunakan lokal yang sama bahwa data saat ini dalam (misalnyaLatin1_General
,French
,Japanese_XJIS
, dll) karena lokal menentukan halaman kode yang digunakan, dan mengubah halaman kode dapat mengubah data (yaitu kehilangan data).CONVERT()
itu akan menggunakan 30 nilai default. Bahayanya adalah, jika string bisa lebih dari 30 byte, itu akan terpotong secara diam-diam dan Anda kemungkinan akan mendapatkan hasil yang salah dari predikat ini.Tidak,
LIKE
tidak selalu peka huruf besar kecil. Ini menggunakan pemeriksaan kolom yang direferensikan, atau pemeriksaan database jika variabel dibandingkan dengan string literal, atau pemeriksaan ditentukan melaluiCOLLATE
klausa opsional .LCASE
bukanlah fungsi SQL Server. Tampaknya itu adalah Oracle atau MySQL. Atau mungkin Visual Basic?Karena konteks pertanyaannya adalah membandingkan kolom dengan string literal, baik pemeriksaan instance (sering disebut sebagai "server") maupun pemeriksaan database tidak berdampak langsung di sini. Kumpulan disimpan per setiap kolom, dan setiap kolom dapat memiliki pemeriksaan yang berbeda, dan pemeriksaan tersebut tidak perlu sama dengan pemeriksaan default database atau pemeriksaan instance. Tentu, pemeriksaan instance adalah default untuk apa yang akan digunakan database yang baru dibuat sebagai pemeriksaan default jika
COLLATE
klausa tidak ditentukan saat membuat database. Dan juga, pemeriksaan default database adalah apa yang akan digunakan kolom yang diubah atau yang baru dibuat jikaCOLLATE
klausa tidak ditentukan.Anda harus menggunakan pemeriksaan case-insensitive yang sebaliknya sama dengan pemeriksaan kolom. Gunakan kueri berikut untuk menemukan pemeriksaan kolom (ubah nama tabel dan nama skema):
SELECT col.* FROM sys.columns col WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName') AND col.[collation_name] IS NOT NULL;
Kemudian ubah saja
_CS
menjadi_CI
. Jadi,Latin1_General_100_CS_AS
akan menjadiLatin1_General_100_CI_AS
.Jika kolom menggunakan pemeriksaan biner (diakhiri dengan
_BIN
atau_BIN2
), temukan pemeriksaan serupa menggunakan kueri berikut:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Misalnya, dengan asumsi kolom menggunakan
Japanese_XJIS_100_BIN2
, lakukan ini:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
Untuk info lebih lanjut tentang collations, encoding, dll, silakan kunjungi: Collations Info
sumber
Tidak, hanya menggunakan
LIKE
tidak akan berhasil.LIKE
mencari nilai yang sama persis dengan pola yang Anda berikan. Dalam hal iniLIKE
hanya akan menemukan teks 'sOmeVal' dan bukan 'someval'.Solusi praktis menggunakan
LCASE()
fungsi tersebut.LCASE('sOmeVal')
mendapatkan string huruf kecil dari teks Anda: 'someval'. Jika Anda menggunakan fungsi ini untuk kedua sisi perbandingan Anda, ini berfungsi:SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
Pernyataan tersebut membandingkan dua string huruf kecil, sehingga 'sOmeVal' Anda akan cocok dengan setiap notasi lain dari 'someval' (mis. 'Someval', 'sOMEVAl' dll.).
sumber
LCASE()
di SQL Server (setidaknya saya tidak bisa melihat). Saya pikir jawaban ini untuk RDBMS yang sama sekali berbeda. Silakan lihat jawaban saya untuk klarifikasi tentang perbandingan string.Anda dapat memaksa case sensitive, mentransmisikan ke varbinary seperti itu:
SELECT * FROM myTable WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
sumber
Anda berada di database apa? Dengan MS SQL Server, ini adalah pengaturan seluruh database, atau Anda dapat menggantinya dengan kata kunci COLLATE.
sumber