LIKE ile eşittir (=)


282

SQL kullanırken =, WHEREyerine bir cümle kullanmanın herhangi bir faydası var LIKEmı?

Herhangi bir özel operatör olmadan LIKEve =aynı, değil mi?


4
Bir db türü belirtmek isteyebilir ... mssql, mysql, oracle?
Allen Rice

1
Sorunuz en az benzer operatör etiketi 5için oy kullanıyor . Eşanlamlı olarak sql-like önermenizi rica edebilir miyim ?
Kermit

@FreshPrinceOfSO, yeterli üne sahip olduğumda bunu yapacağım. Teşekkürler.
Travis

Yanıtlar:


271

Farklı Operatörler

LIKEve =farklı operatörlerdir. Buradaki yanıtların çoğu, bu operatörler arasındaki tek fark olmayan joker karakter desteğine odaklanıyor!

=sayı ve karakter dizileri üzerinde çalışan bir karşılaştırma operatörüdür. Dizeleri karşılaştırırken karşılaştırma operatörü tüm dizeleri karşılaştırır .

LIKEbir karakter karakter karşılaştırır dize işleci .

Konuları karmaşıklaştırmak için, her iki operatör de karşılaştırmanın sonucu üzerinde önemli etkileri olabilecek bir harmanlama kullanır .

Motive Edici Örnek

Önce bu operatörlerin açıkça farklı sonuçlar ürettikleri bir örnek belirleyelim. MySQL kılavuzundan alıntı yapmama izin ver:

SQL standardına göre LIKE, karakter başına esasına göre eşleştirme gerçekleştirir, böylece = karşılaştırma işlecinden farklı sonuçlar üretebilir:

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 |
+--------------------------------------+

Lütfen MySQL kılavuzunun bu sayfasına Dize Karşılaştırma İşlevleri adı =verildiğini ve bu konuların tartışılmadığını unutmayın;= bir dize karşılaştırma işlevi olmadığını unutmayın.

Nasıl =Çalışır?

SQL Standart § 8.2 açıklamaktadır =dizeleri karşılaştırır:

İki karakter dizesinin karşılaştırması aşağıdaki gibi belirlenir:

a) X karakterlerindeki uzunluk, Y karakterlerindeki uzunluğa eşit değilse, daha kısa dize, karşılaştırma amacıyla, kendisinin uzun dizenin uzunluğuna uzatılmış bir kopyasıyla etkili bir şekilde değiştirilir. ped karakterinin CS'ye göre seçildiği bir veya daha fazla ped karakterinin sağında birleştirme ile. CS NO PAD özniteliğine sahipse, pad karakteri, X ve Y karakter kümesindeki CS altındaki herhangi bir dizeden daha az harmanlayan herhangi bir karakterden farklı, uygulamaya bağlı bir karakterdir. Aksi takdirde, pad karakteri a şeklindedir.

b) X ve Y karşılaştırmasının sonucu, harmanlama sekansı CS ile verilir.

c) Harmanlama sırasına bağlı olarak, farklı uzunluklarda olsa veya farklı karakter dizileri içeriyor olsalar bile, iki dize eşit olarak karşılaştırılabilir. MAX, MIN, DISTINCT işlemleri, bir gruplama sütununa başvurular ve UNION, EXCEPT ve INTERSECT işleçleri karakter dizelerine başvurduğunda, bu işlemler tarafından bu tür bir eşit değer kümesinden seçilen belirli değer uygulamaya bağlıdır.

(Vurgu eklenmiştir.)

Ne anlama geliyor? Bu, dizeleri karşılaştırırken, =operatörün mevcut harmanlama etrafında sadece ince bir sargı olduğu anlamına gelir . Harmanlama, dizeleri karşılaştırmak için çeşitli kurallara sahip bir kütüphanedir. İşte MySQL'den ikili bir harmanlama örneği :

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);
}

Bu özel harmanlama bayt byte baytı karşılaştırır (bu yüzden "ikili" olarak adlandırılır - dizelere özel bir anlam vermez). Diğer harmanlamalar daha gelişmiş karşılaştırmalar sağlayabilir.

Örneğin, büyük / küçük harfe duyarlı olmayan karşılaştırmaları destekleyen bir UTF-8 harmanlaması . Kod buraya yapıştırmak için çok uzun, ama bu bağlantıya gidin ve gövdesini okuyun my_strnncollsp_utf8mb4(). Bu harmanlama bir seferde birden fazla bayt işleyebilir ve çeşitli dönüşümler uygulayabilir (büyük / küçük harf duyarsız karşılaştırma gibi). =Operatör tamamen harmanlama kaprisleri soyutlanmış bir.

Nasıl LIKEÇalışır?

SQL Standart § 8.5 açıklamaktadır LIKEdizeleri karşılaştırır:

<predicate>

M LIKE P

M'nin alt dizelere bölümlenmesi varsa doğrudur:

i) M'nin bir alt dizisi, M'nin 0 veya daha fazla bitişik <karakter gösterimi> s dizisidir ve M'nin her <karakter gösterimi> tam olarak bir alt dizenin bir parçasıdır.

ii) P'nin i-alt alt dizesi belirteci rasgele bir karakter belirleyicisi ise, M'nin i-alt alt dizesi herhangi bir <karakter temsili> dir.

iii) P'nin i-th alt dizesi tanımlayıcısı isteğe bağlı bir dize tanımlayıcısıysa, M'nin i-alt alt dizisi 0 veya daha fazla <karakter temsili> s dizisidir.

iv) P'nin i-th alt dizesi belirleyicisi ne rastgele bir karakter belirleyicisi ne de rastgele bir dize belirleyicisi değilse, M'nin i-alt alt dizesi, <benzer yüklem> öğesinin harmanlama sırasına göre bu alt dize belirtecine eşittir. <boşluk> karakterlerinin M'ye eklenmesi ve bu alt dize belirleyicisiyle aynı uzunlukta olması gerekir.

v) M'nin alt dize sayısı P'nin alt dize belirteçlerinin sayısına eşittir.

(Vurgu eklenmiştir.)

Bu oldukça garip, hadi onu yıkalım. İi ve iii maddeleri sırasıyla joker karakterlere _ve %Herhangi Pbir joker karakter içermiyorsa, yalnızca iv. Öğe uygulanır. Bu OP tarafından ortaya çıkarılan bir ilgi durumudur.

Bu durumda, geçerli harmanlamayı kullanarak her bir "alt dizeyi" (tek tek karakterler) Mher bir alt dizeyle Pkarşılaştırır.

Sonuçlar

En alt satır, dizeleri =karşılaştırırken, tüm dizeyi LIKEkarşılaştırırken bir kerede bir karakter karşılaştırmasıdır. Her iki karşılaştırma da geçerli harmanlamayı kullanır. Bu fark, bu yazıda ilk örnekte görüldüğü gibi, bazı durumlarda farklı sonuçlara yol açmaktadır.

Hangisini kullanmalısın? Kimse size bunu söyleyemez - kullanım durumunuz için doğru olanı kullanmanız gerekir. Karşılaştırma işleçlerini değiştirerek zamanından önce optimize etmeyin.


4
"EQUALS, iki veri bayt bayt baytını karşılaştırır": aşırı basitleştirilmiş ve çoğu zaman doğru değildir, çünkü EQUALS (=) davranışı COLLATE ile değiştirilebilir ve karakter yerine karakter sınıflarının karşılaştırılmasına neden olur. Örneğin, bkz. Dev.mysql.com/doc/refman/5.0/en/charset-collate.html (MySQL) veya sqlmag.com/blog/forcing-collation-where-clause-22-jun-2011 (SQL Server).
Peter B

11
Bu doğru cevap. Ne yaptığını biliyoruz LIKE, ancak bu cevap, LIKEolmadan %veya _mevcut olmadan kullanmanın , kullanımla aynı olmadığını açık bir şekilde açıklıyor =. Cevabınız binlerce oy alsın.
rinogo

1
@mehase bu doğru olamaz. Varchar alanım değeri içeriyorsa 'AbCdEfG've ben de WHERE MyCol = 'abcdefg', bayt byte bayt eşdeğeri olmamasına rağmen yine de bu satırı geri alıyorum
Kip

1
PeterB ve @Kip iyi puanlar veriyor. Harmanlamanın bu operatörleri nasıl etkilediğini açıklamaya çalışmak için cevabımı geliştirdim.
Mark E. Haase

2
Bu artık doğru görünmüyor: set charset latin1; SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;0 SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;veriyor ve 0 veriyor.
joanq

170

Equals (=) operatörü "karşılaştırma operatörü eşitlik için iki değeri karşılaştırır." Başka bir deyişle, bir SQL deyiminde, denklemin her iki tarafı eşit olmadığı sürece true değerini döndürmez. Örneğin:

SELECT * FROM Store WHERE Quantity = 200;

LIKE işleci, bir dize değerini joker karakter içeren bir desen dizesiyle eşleştirmeye çalışan "bir desen eşleştirme karşılaştırması" uygular. Örneğin:

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

LIKE genellikle sadece dizelerle kullanılır ve eşittir (sanırım) daha hızlıdır. Eşittir işleci joker karakterlere gerçek karakter olarak davranır. Döndürülen sonuçlardaki fark aşağıdaki gibidir:

SELECT * FROM Employees WHERE Name = 'Chris';

Ve

SELECT * FROM Employees WHERE Name LIKE 'Chris';

LIKE kullanmak genellikle bir desen eşleşmesi olarak daha uzun sürer olsa da, aynı sonucu dönecekti. Ancak,

SELECT * FROM Employees WHERE Name = 'Chris%';

Ve

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

"=" Kullanıldığında yalnızca "Chris%" döndürülür ve LIKE operatörü "Chris" ile başlayan her şeyi döndürür.

Umarım yardımcı olur. Bazı iyi bilgileri burada bulabilirsiniz .


108
OP'nin LIKE'yi ne zaman ve ne zaman kullanacağını bildiği izlenimi altındayım = sadece joker karakter olmadığında bir performans farkı olup olmadığını merak ediyor. Bu cevap kısaca buna değinir, ancak bu cevabın% 95'inin gerçekten alakalı olmadığını hissediyorum.
Yasadışı Programcı

1
Çok doğru. Soruyu cevaplarken aynı olup olmadığından emin değilim. Eğer öyleyse, performans hakkında soru soran kısmı kaçırdım. Gözlem için teşekkürler.
achinda99

9
Bu cevap korkunç. LIKE ve '=' tamamen farklı operatörlerdir, ancak bazı küçük alt gruplarda da benzer şekilde davranırlar. Posterity uğruna, lütfen buradaki yanıtların geri kalanını okuyun veya bunu belleğe vermeden önce en azından "mysql like" için google.
Mark E. Haase

3
Öte yandan, bu cevap sahip olduğum ve aradığım soruyu yanıtladı. Bazen bir yanıtın bir sorunun başlığını içerik kadar cevaplaması da iyidir.
CorayThan

Hatırlamak için iyi bir fikir, char ve varchar2'yi kullandığınız zamandır. Char'ı char ile karşılaştırırsanız. Veritabanı karşılaştırmadan önce ilk 'değişken' uzunluğunu ikincinin aynıına dönüştürün. Char ve varchar2'yi karşılaştırırsanız veritabanı hiçbir şey yapmaz. docs.oracle.com/cd/A64702_01/doc/server.805/a58236/c_char.htm
xild

18

Bu, 'vs' = 'performansı gibi SQL sorusu için başka bir cevabımın bir kopyası / yapıştırmasıdır :

MySQL 5.5 kullanarak kişisel bir örnek: 2 tablo, 3 milyon sıradan biri ve 10 bin sıradan biri arasında bir iç birleşim vardı.

Aşağıdaki gibi bir dizinde bir benzeri kullanılırken (joker karakterler yok), yaklaşık 30 saniye sürdü:

where login like '12345678'

'açıkla' kullanarak şunu elde ederim:

resim açıklamasını buraya girin

Aynı sorguda '=' kullanılırken, yaklaşık 0.1 saniye sürdü:

where login ='12345678'

'Anlat' kullanarak şunu elde ederim:

resim açıklamasını buraya girin

Gördüğünüz gibi like, dizin aramasını tamamen iptal etti, bu yüzden sorgu 300 kat daha fazla zaman aldı.


17

LIKEve =farklı. LIKEbir arama sorgusunda kullanacağınız şeydir. Ayrıca _(basit karakter joker karakteri) ve %(çok karakterli joker karakter) gibi joker karakterlere izin verir .

= tam eşleşme istiyorsanız kullanılmalıdır ve daha hızlı olacaktır.

Bu site açıklıyor LIKE


11

Bir fark - LIKE ile joker karakterler kullanma olasılığı dışında - arka boşluklardadır: = operatörü arka boşluğu yok sayar, ancak LIKE kullanmaz.


4
Bu MySQL ve MS SQL için geçerli olsa da, bu PostgreSQL için geçerli değildir.
Bruno

10

Veritabanı sistemine bağlıdır.

Genelde özel karakterler olmadan evet, = ve LIKE aynıdır.

Bununla birlikte, bazı veritabanı sistemleri, harmanlama ayarlarını farklı işleçlerle farklı şekilde ele alabilir.

Örneğin, MySQL'de = on dizeleri ile karşılaştırmalar her zaman varsayılan olarak büyük / küçük harfe duyarlı değildir, bu nedenle özel karakterler içermeyen LIKE aynıdır. Diğer bazı RDBMS'lerin LIKE değeri büyük / küçük harfe duyarlı değildir, ancak = değildir.


Bu tuhaflığa genel bakış gibi bir şey var mı?
Gumbo

9

Bu örnekte varcharcol'un ''bu sütuna karşı boş hücre içermediğini ve boş hücre içermediğini kabul ediyoruz

select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''

Birincisi 0 satır çıktısı verirken ikincisi tüm listeyi gösterir. = bir filtre gibi davranırken, kesinlikle eşleşir. filtrenin ölçütleri yoksa, her veri geçerlidir.

gibi - amacı nedeniyle biraz daha yavaş çalışır ve varchar ve benzer verilerle kullanım için tasarlanmıştır.


6

Tam eşleşme ararsanız, = ve LIKE değerlerini kullanabilirsiniz.

Bu durumda "=" kullanmak biraz daha hızlıdır (tam eşleşme aranıyor) - SQL Server Management Studio'da aynı sorguyu iki kez, bir kez "=" kullanarak, bir kez "LIKE" kullanarak ve ardından "Sorgu" / "Gerçek yürütme planını dahil et" seçeneğini kullanın.

İki sorguyu yürütün; sonuçlarınızı iki kez ve iki gerçek yürütme planını görmelisiniz. Benim durumumda,% 50'ye karşı% 50'ye bölündüler, ancak "=" yürütme planında daha küçük bir "tahmini alt ağaç maliyeti" var (en soldaki "SEÇİM" kutusunun üzerine geldiğinizde görüntülenir) - ancak yine, gerçekten büyük bir fark değil.

Ancak, LIKE ifadenizdeki joker karakterlerle aramaya başladığınızda, arama performansı azalır. "LIKE Mill%" araması oldukça hızlı olabilir - SQL Server, varsa, bu sütunda bir dizin kullanabilir. SQL Server'ın bu aramayı tatmin etmesinin tek yolu tam tablo taraması yapmak olduğundan, "LIKE% expression%" ifadesini aramak son derece yavaştır. Bu yüzden GİBİ'lerinize dikkat edin!

üzüm posası


-1 hayır, her zaman biraz daha hızlı değil. Sütun% mystring% kullanılarak endekslenirse, birkaç büyüklük sırası daha yavaştır. Gerçekten de tuzlarına değer herhangi bir kod standardı, bir micky fare veritabanından daha büyük herhangi bir zamanki gibi ne zaman ve ne zaman kullanılmayacağına dair sıkı kurallara sahip olacaktır.
Cruachan

1
Tüm vakalar için biraz daha yavaş olacağını hiç söylemedim - bir EXACT eşleşmesi ararsanız bunun biraz daha yavaş olacağını söyledim. Elbette, bir LIKE ile arama yapmak ve özellikle arama öğenizin başında ve sonunda joker karakterler kullanmak, bundan çok daha yavaştır.
marc_s

Ve evet, katılıyorum - kişi ne zaman LIKE kullanılacağına veya kullanılamayacağına dair net kurallara sahip olmalıdır (sadece joker karakterlerle arama yapmanız gerektiğinde). Ama sonra tekrar - teoride, teori ve pratik arasında hiçbir fark yok, ama pratikte .......
marc_s

6

= Kullanıldığında, sorguyu çalışma zamanında oluşturduğunuzda dizede joker karakterler ve özel karakter çakışmaları önlenir.

Bu, LIKE yan tümcesinde kayabilecek tüm özel joker karakterlerden kaçmak zorunda kalmadan ve amaçlanan sonucu üretmeden programcının hayatını kolaylaştırır. Sonuçta, =% 99 kullanım senaryosu, her seferinde onlardan kaçmak bir acı olur.

90'larda gözlerini deviriyor

Ayrıca biraz daha yavaş olduğundan şüpheliyim, ancak desende joker karakter olmaması önemli.


6

Performansla ilgili orijinal soruyu ele almak için, endeks kullanımı söz konusudur . Basit bir tablo taraması gerçekleştiğinde, "LIKE" ve "=" aynıdır . Dizinler söz konusu olduğunda , LIKE yantümcesinin nasıl oluştuğuna bağlıdır . Daha spesifik olarak, joker karakterlerin yeri nedir?


Aşağıdakileri göz önünde bulundur:

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

"=" Vs "LIKE" kullanılırken sorgu planının oluşturulmasında da ihmal edilebilir bir fark olabilir.


4

Joker karakterlerin yanı sıra, =AND arasındaki fark LIKEhem SQL sunucusunun türüne hem de sütun türüne bağlı olacaktır.

Bu örneği ele alalım:

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 '
  • Kullanımı MS SQL Server 2012 , arkada kalan boşluklar hariç, karşılaştırmalı olarak göz ardı edilecektir LIKEkolon tipi olduğu zaman VARCHAR.

  • Kullanma MySQL 5.5 , arkada kalan boşluklar için göz ardı edilecektir =, ancak için LIKE, her ikisi de CHARve VARCHAR.

  • Kullanma PostgreSQL 9.1 , boşluk hem de önemli olan =ve LIKEkullanılarak VARCHAR, fakat ile CHAR(bakınız belgeler ).

    İle davranışı LIKEdaCHAR .

    Yukarıdaki verilerle aynı verileri kullanmak CAST, sütun adında bir belirti kullanmak da bir fark yaratır :

    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)

    Bu yalnızca "CAST hem" ve "CAST col" satırlarını döndürür.


2

LIKE anahtar kelimesi kuşkusuz bir "performans fiyat etiketi" eklenmiş olarak gelir. Bununla birlikte, sorgunuzda kullanılacak joker karakterleri içerebilecek bir giriş alanınız varsa, yalnızca aşağıdaki durumlarda LIKE kullanmanızı öneririm , girdi joker kartlardan birini içeriyorsa . Aksi takdirde, karşılaştırmaya eşit olan standardı kullanın.

Saygılarımla...


1

Gerçekten sorgunun ne yapmasını istediğinize gelir. Tam eşleme demek istiyorsanız = kullanın. Daha bulanık bir eşleşme demek istiyorsanız, GİBİ kullanın. Ne demek istediğinizi söylemek, genellikle kodlu iyi bir politikadır.


1

Oracle'da, joker karakter içermeyen bir "like", "eşittir" ile aynı sonucu döndürür, ancak ek işlem gerektirebilir. Tom Kyte'e göre Oracle, değişmez değerleri kullanırken joker karakter içermeyen bir "like" ı "değişmez" olarak ele alacak, ancak bağlama değişkenlerini kullanırken değil.


0

=ve LIKEaynı değil;

  1. = tam dizeyle eşleşir
  2. LIKE joker karakterler (%) içerebilecek bir dizeyle eşleşir

2
Yetersiz Cevap

Joker karakter olmadan kullanılabilir. Soru aynı vakalar için farklılığı sordu.
M-Razavi
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.