Bila menggunakan SQL, apakah ada manfaat menggunakan =
dalam WHERE
klausul bukan LIKE
?
Tanpa operator khusus, LIKE
dan =
apakah sama, kan?
5
suara untuk tag seperti operator . Bisakah saya meminta Anda menyarankan seperti sql sebagai sinonim ?
Bila menggunakan SQL, apakah ada manfaat menggunakan =
dalam WHERE
klausul bukan LIKE
?
Tanpa operator khusus, LIKE
dan =
apakah sama, kan?
5
suara untuk tag seperti operator . Bisakah saya meminta Anda menyarankan seperti sql sebagai sinonim ?
Jawaban:
LIKE
dan =
merupakan operator yang berbeda. Sebagian besar jawaban di sini fokus pada dukungan wildcard, yang bukan satu-satunya perbedaan antara operator-operator ini!
=
adalah operator perbandingan yang beroperasi pada angka dan string. Saat membandingkan string, operator perbandingan membandingkan seluruh string .
LIKE
adalah operator string yang membandingkan karakter dengan karakter .
Untuk memperumit masalah, kedua operator menggunakan collation yang dapat memiliki efek penting pada hasil perbandingan.
Mari kita pertama-tama mengidentifikasi contoh di mana operator ini menghasilkan hasil yang jelas berbeda. Izinkan saya mengutip dari manual MySQL:
Per standar SQL, LIKE melakukan pencocokan pada basis per karakter, sehingga ia dapat menghasilkan hasil yang berbeda dari operator = pembanding:
mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
| 0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
| 1 |
+--------------------------------------+
Harap dicatat bahwa halaman manual MySQL ini disebut String Comparison Functions , dan =
tidak dibahas, yang menyiratkan hal itu=
ini bukan semata-mata fungsi perbandingan string.
=
kerjanya?The SQL Standard § 8.2 menggambarkan bagaimana=
membandingkan string:
Perbandingan dua string karakter ditentukan sebagai berikut:
a) Jika panjang karakter X tidak sama dengan panjang karakter Y, maka string yang lebih pendek secara efektif diganti, untuk tujuan perbandingan, dengan salinannya sendiri yang telah diperpanjang hingga panjang string yang lebih panjang. oleh penggabungan di sebelah kanan satu atau lebih karakter pad, di mana karakter pad dipilih berdasarkan CS. Jika CS memiliki atribut NO PAD, maka karakter pad adalah karakter yang bergantung pada implementasi yang berbeda dari karakter apa pun dalam set karakter X dan Y yang menyusun kurang dari string apa pun di bawah CS. Jika tidak, karakter pad adalah a.
b) Hasil perbandingan X dan Y diberikan oleh CS urutan sekuensing.
c) Bergantung pada urutan penyatuan, dua string dapat membandingkan sama bahkan jika mereka memiliki panjang yang berbeda atau mengandung urutan karakter yang berbeda. Ketika operasi MAX, MIN, DISTINCT, referensi ke kolom pengelompokan, dan operator UNION, KECUALI, dan INTERSECT mengacu pada string karakter, nilai spesifik yang dipilih oleh operasi ini dari serangkaian nilai yang sama bergantung pada implementasi.
(Penekanan ditambahkan.)
Apa artinya ini? Ini berarti bahwa ketika membandingkan string, =
operator hanyalah pembungkus tipis di sekitar susunan saat ini. Kolasi adalah perpustakaan yang memiliki berbagai aturan untuk membandingkan string. Berikut adalah contoh pengumpulan biner dari MySQL :
static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
const uchar *s, size_t slen,
const uchar *t, size_t tlen,
my_bool t_is_prefix)
{
size_t len= MY_MIN(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}
Susunan khusus ini terjadi untuk membandingkan byte-by-byte (itulah sebabnya ini disebut "biner" - tidak memberikan makna khusus pada string). Koleksi lainnya dapat memberikan perbandingan yang lebih maju.
Misalnya, berikut ini adalah susunan UTF-8 yang mendukung perbandingan case-insensitive. Kode ini terlalu panjang untuk ditempelkan di sini, tetapi buka tautan itu dan baca isi my_strnncollsp_utf8mb4()
. Susunan ini dapat memproses beberapa byte sekaligus dan dapat menerapkan berbagai transformasi (seperti perbandingan tidak sensitif huruf). Itu=
operator benar-benar disarikan dari keanehan pemeriksaan tersebut.
LIKE
kerjanya?The SQL Standard § 8,5 menjelaskan bagaimana LIKE
membandingkan string:
The <predicate>
M LIKE P
benar jika ada partisi M menjadi substring sehingga:
i) Substring M adalah urutan 0 atau lebih berdekatan <representasi karakter> s dari M dan setiap <representasi karakter> M adalah bagian dari satu substring.
ii) Jika specifier substring ke-i dari P adalah specifier karakter yang berubah-ubah, substring ke-i dari M adalah sembarang <representasi karakter> tunggal.
iii) Jika specifier substring ke-i dari P adalah specifier string arbitrer, maka substring ke-i dari M adalah setiap urutan 0 atau lebih <representasi karakter> s.
iv) Jika specifier substring ke-i dari P bukanlah specifier karakter arbitrer atau specifier string arbitrer, maka substring ke-i dari M sama dengan specifier substring tersebut sesuai dengan urutan susunan <predikat seperti>, tanpa menambahkan karakter <spasi> ke M, dan memiliki panjang yang sama dengan specifier substring itu.
v) Jumlah substring M sama dengan jumlah penentu substring P.
(Penekanan ditambahkan.)
Ini cukup bertele-tele, jadi mari kita jabarkan. Item ii dan iii merujuk ke wildcard _
dan %
, masing-masing. Jika P
tidak mengandung wildcard, maka hanya item iv yang berlaku. Ini adalah kasus bunga yang ditimbulkan oleh OP.
Dalam hal ini, ia membandingkan setiap "substring" (karakter individu) M
terhadap setiap substring dalam P
menggunakan susunan saat ini.
Intinya adalah ketika membandingkan string, =
membandingkan seluruh string sambil LIKE
membandingkan satu karakter pada suatu waktu. Kedua perbandingan menggunakan susunan saat ini. Perbedaan ini menyebabkan hasil yang berbeda dalam beberapa kasus, sebagaimana dibuktikan dalam contoh pertama dalam posting ini.
Yang mana yang harus Anda gunakan? Tidak ada yang bisa memberi tahu Anda - Anda perlu menggunakan yang benar untuk use case Anda. Jangan mengoptimalkan secara prematur dengan mengganti operator perbandingan.
LIKE
dilakukan, tetapi jawaban ini dengan luar biasa menjelaskan bahwa menggunakan LIKE
tanpa %
atau _
hadir sama sekali tidak sama dengan menggunakan =
. Semoga jawaban Anda menerima seribu upvotes.
'AbCdEfG'
, dan saya lakukan WHERE MyCol = 'abcdefg'
, saya masih mendapatkan baris itu kembali, meskipun mereka jelas tidak setara byte-by-byte
set charset latin1;
SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
memberi 0, dan SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
memberi 0 juga.
Operator equals (=) adalah "operator perbandingan membandingkan dua nilai untuk kesetaraan." Dengan kata lain, dalam pernyataan SQL, itu tidak akan kembali benar kecuali kedua sisi persamaan sama. Sebagai contoh:
SELECT * FROM Store WHERE Quantity = 200;
Operator LIKE "mengimplementasikan perbandingan kecocokan pola" yang mencoba untuk mencocokkan "nilai string terhadap string pola yang berisi karakter wild-card." Sebagai contoh:
SELECT * FROM Employees WHERE Name LIKE 'Chris%';
LIKE umumnya hanya digunakan dengan string dan equals (saya percaya) lebih cepat. Operator yang sama memperlakukan karakter wild card sebagai karakter literal. Perbedaan dalam hasil yang dikembalikan adalah sebagai berikut:
SELECT * FROM Employees WHERE Name = 'Chris';
Dan
SELECT * FROM Employees WHERE Name LIKE 'Chris';
Akan mengembalikan hasil yang sama, meskipun menggunakan LIKE umumnya akan lebih lama karena kecocokan polanya. Namun,
SELECT * FROM Employees WHERE Name = 'Chris%';
Dan
SELECT * FROM Employees WHERE Name LIKE 'Chris%';
Akan mengembalikan hasil yang berbeda, di mana menggunakan "=" menghasilkan hanya hasil dengan "Chris%" dikembalikan dan operator LIKE akan mengembalikan apa pun yang dimulai dengan "Chris".
Semoga itu bisa membantu. Beberapa info bagus dapat ditemukan di sini .
Ini adalah salinan / rekatkan jawaban saya yang lain untuk pertanyaan kinerja SQL 'like' vs '=' :
Contoh pribadi menggunakan mysql 5.5: Saya memiliki gabungan dalam antara 2 tabel, satu dari 3 juta baris dan satu dari 10 ribu baris.
Saat menggunakan sejenis pada indeks seperti di bawah ini (tidak ada wildcard), butuh sekitar 30 detik:
where login like '12345678'
menggunakan 'jelaskan' saya dapatkan:
Saat menggunakan '=' pada permintaan yang sama, butuh sekitar 0,1 detik:
where login ='12345678'
Menggunakan 'jelaskan' saya dapatkan:
Seperti yang Anda lihat, like
pencarian indeks yang dibatalkan sepenuhnya, jadi kueri membutuhkan waktu 300 kali lebih banyak.
LIKE
dan =
berbeda. LIKE
adalah apa yang akan Anda gunakan dalam permintaan pencarian. Ini juga memungkinkan wildcard seperti _
(karakter wildcard sederhana) dan%
(wildcard multi-karakter).
=
harus digunakan jika Anda ingin kecocokan yang tepat dan itu akan lebih cepat.
Tergantung pada sistem basis data.
Umumnya tanpa karakter khusus, ya, = dan LIKE sama.
Namun, beberapa sistem database mungkin memperlakukan pengaturan collation secara berbeda dengan operator yang berbeda.
Sebagai contoh, dalam perbandingan MySQL dengan = pada string selalu case-insensitive secara default, jadi LIKE tanpa karakter khusus adalah sama. Pada beberapa LIKE RDBMS lainnya adalah case-insensitive sementara = tidak.
Untuk contoh ini kita anggap remeh bahwa varcharcol tidak mengandung ''
dan tidak memiliki sel kosong di kolom ini
select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''
Yang pertama menghasilkan 0 baris output sedangkan yang kedua menunjukkan seluruh daftar. = adalah kasus yang benar-benar cocok sementara suka bertindak seperti filter. jika filter tidak memiliki kriteria, setiap data valid.
suka - berdasarkan fungsinya bekerja sedikit lebih lambat dan dimaksudkan untuk digunakan dengan varchar dan data serupa.
Jika Anda mencari yang sama persis, Anda bisa menggunakan keduanya, = dan LIKE.
Menggunakan "=" sedikit lebih cepat dalam hal ini (mencari kecocokan yang tepat) - Anda dapat memeriksanya sendiri dengan memiliki kueri yang sama dua kali dalam SQL Server Management Studio, sekali menggunakan "=", sekali menggunakan "LIKE", dan lalu gunakan "Permintaan" / "Sertakan rencana eksekusi aktual".
Jalankan dua pertanyaan dan Anda akan melihat hasil Anda dua kali, ditambah dua rencana eksekusi yang sebenarnya. Dalam kasus saya, mereka dibagi 50% vs 50%, tetapi "=" rencana eksekusi memiliki "perkiraan biaya subtree" yang lebih kecil (ditampilkan ketika Anda mengarahkan kursor ke kotak "SELECT" paling kiri) - tetapi sekali lagi, itu benar-benar bukan perbedaan besar.
Tetapi ketika Anda mulai mencari dengan wildcard dalam ekspresi LIKE Anda, kinerja pencarian akan meredup. Cari "LIKE Mill%" masih bisa cukup cepat - SQL Server dapat menggunakan indeks pada kolom itu, jika ada. Mencari "LIKE% ekspresi%" sangat lambat, karena satu-satunya cara SQL Server dapat memuaskan pencarian ini adalah dengan melakukan pemindaian tabel penuh. Jadi berhati-hatilah dengan LIKE Anda!
Marc
Menggunakan = menghindari wildcard dan konflik karakter khusus dalam string ketika Anda membangun kueri saat run time.
Ini membuat hidup programmer lebih mudah dengan tidak harus melarikan diri dari semua karakter wildcard khusus yang mungkin tergelincir dalam klausa LIKE dan tidak menghasilkan hasil yang diinginkan. Lagipula, = adalah skenario use case 99%, akan sulit untuk melarikan diri setiap saat.
memutar mata pada '90 -an
Saya juga menduga itu sedikit lebih lambat, tapi saya ragu itu penting jika tidak ada wildcard dalam polanya.
Untuk menjawab pertanyaan awal tentang kinerja, ia turun ke pemanfaatan indeks . Ketika pemindaian tabel sederhana terjadi, "LIKE" dan "=" identik . Ketika indeks terlibat, itu tergantung pada bagaimana klausa LIKE terbentuk. Lebih khusus lagi, apa lokasi wildcard (s)?
Pertimbangkan yang berikut ini:
CREATE TABLE test(
txt_col varchar(10) NOT NULL
)
go
insert test (txt_col)
select CONVERT(varchar(10), row_number() over (order by (select 1))) r
from master..spt_values a, master..spt_values b
go
CREATE INDEX IX_test_data
ON test (txt_col);
go
--Turn on Show Execution Plan
set statistics io on
--A LIKE Clause with a wildcard at the beginning
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '%10000'
--Results in
--Table 'test'. Scan count 3, logical reads 15404, physical reads 2, read-ahead reads 15416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index SCAN is 85% of Query Cost
--A LIKE Clause with a wildcard in the middle
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '1%99'
--Results in
--Table 'test'. Scan count 1, logical reads 3023, physical reads 3, read-ahead reads 3018, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost for test data, but it may result in a Table Scan depending on table size/structure
--A LIKE Clause with no wildcards
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO
--an "=" clause = does Index Seek same as above
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col = '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO
DROP TABLE test
Mungkin juga ada perbedaan yang dapat diabaikan dalam pembuatan rencana kueri saat menggunakan "=" vs "LIKE".
Selain wildcard, perbedaan antara =
AND LIKE
akan bergantung pada jenis SQL server dan pada tipe kolom.
Ambil contoh ini:
CREATE TABLE testtable (
varchar_name VARCHAR(10),
char_name CHAR(10),
val INTEGER
);
INSERT INTO testtable(varchar_name, char_name, val)
VALUES ('A', 'A', 10), ('B', 'B', 20);
SELECT 'VarChar Eq Without Space', val FROM testtable WHERE varchar_name='A'
UNION ALL
SELECT 'VarChar Eq With Space', val FROM testtable WHERE varchar_name='A '
UNION ALL
SELECT 'VarChar Like Without Space', val FROM testtable WHERE varchar_name LIKE 'A'
UNION ALL
SELECT 'VarChar Like Space', val FROM testtable WHERE varchar_name LIKE 'A '
UNION ALL
SELECT 'Char Eq Without Space', val FROM testtable WHERE char_name='A'
UNION ALL
SELECT 'Char Eq With Space', val FROM testtable WHERE char_name='A '
UNION ALL
SELECT 'Char Like Without Space', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'Char Like With Space', val FROM testtable WHERE char_name LIKE 'A '
Menggunakan MS SQL Server 2012 , spasi tambahan akan diabaikan dalam perbandingan, kecuali dengan LIKE
saat tipe kolom VARCHAR
.
Menggunakan MySQL 5.5 , spasi tambahan akan diabaikan =
, tetapi tidak untukLIKE
, baik dengan CHAR
dan VARCHAR
.
Menggunakan PostgreSQL 9.1 , spasi signifikan dengan keduanya =
dan LIKE
menggunakanVARCHAR
, tetapi tidak dengan CHAR
(lihat dokumentasi ).
Perilaku dengan LIKE
juga berbeda denganCHAR
.
Menggunakan data yang sama seperti di atas, menggunakan eksplisit CAST
pada nama kolom juga membuat perbedaan :
SELECT 'CAST none', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'CAST both', val FROM testtable WHERE
CAST(char_name AS CHAR) LIKE CAST('A' AS CHAR)
UNION ALL
SELECT 'CAST col', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE 'A'
UNION ALL
SELECT 'CAST value', val FROM testtable WHERE char_name LIKE CAST('A' AS CHAR)
Ini hanya mengembalikan baris untuk "CAST baik" dan "CAST col".
Kata kunci LIKE tidak diragukan lagi dilengkapi dengan "label harga kinerja" yang terlampir. Yang mengatakan, jika Anda memiliki bidang input yang berpotensi memasukkan karakter wild card untuk digunakan dalam permintaan Anda, saya akan merekomendasikan menggunakan LIKE hanya jika input berisi salah satu wild card. Kalau tidak, gunakan standar yang sama dengan perbandingan.
Salam Hormat...
Di Oracle, 'suka' tanpa wildcard akan mengembalikan hasil yang sama dengan 'sama', tetapi bisa memerlukan pemrosesan tambahan. Menurut Tom Kyte , Oracle akan memperlakukan 'like' tanpa wildcard sebagai 'equals' saat menggunakan literal, tetapi tidak ketika menggunakan variabel bind.