같음 (=) 대 LIKE


281

SQL을 사용할 때 ? 대신 절 =에서 사용하면 어떤 이점 WHERELIKE있습니까?

특별한 연산자가 LIKE없고 =동일합니까?


4
db 유형 ... mssql, mysql 또는 oracle을 지정하고 싶습니까?
Allen Rice

1
귀하의 질문에 최소한 유사 운영자 태그에 5대한 투표권이 있습니다. sql-like동의어 로 제안하도록 친절하게 요청할 수 있습니까?
커밋

@FreshPrinceOfSO, 나는 충분한 명성을 얻으면 그렇게 할 것입니다. 감사.
트래비스

답변:


271

다른 연산자

LIKE그리고 =다른 사업자입니다. 여기에있는 대부분의 답변은 와일드 카드 지원에 중점을 두는데,이 연산자들 간의 유일한 차이점은 아닙니다!

=숫자와 문자열에서 작동하는 비교 연산자입니다. 문자열을 비교할 때 비교 연산자는 전체 문자열을 비교합니다 .

LIKE문자를 문자별로 비교하는 문자열 연산자입니다 .

문제를 복잡하게하기 위해 두 연산자 는 비교 결과에 중요한 영향을 줄 수 있는 데이터 정렬 을 사용합니다 .

동기 부여 예

먼저 이러한 연산자가 분명히 다른 결과를 생성하는 예를 살펴 보겠습니다. MySQL 매뉴얼에서 인용 할 수 있습니다.

SQL 표준에 따라 LIKE는 문자별로 일치를 수행하므로 = 비교 연산자와 다른 결과를 생성 할 수 있습니다.

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

MySQL 매뉴얼의이 페이지는 String Comparison Functions 이며, =논의되지 않았으므로 이는 =엄격하게 문자열 비교 함수가 아니라는 것을 의미 합니다.

어떻게 =작동합니까?

SQL 표준 § 8.2 방법에 대해 설명 =문자열을 비교 :

두 문자열의 비교는 다음과 같이 결정됩니다.

a) X 문자의 길이가 Y 문자의 길이와 같지 않으면 짧은 문자열은 비교를 위해 긴 문자열의 길이로 확장 된 자체 사본으로 효과적으로 대체됩니다. 하나 이상의 패드 문자의 오른쪽에 연결하여 패드 문자가 CS를 기준으로 선택됩니다. CS에 NO PAD 속성이있는 경우 패드 문자는 X 및 Y의 문자 세트에있는 문자와 다른 구현 종속 문자이며 CS의 문자열보다 작게 대조됩니다. 그렇지 않으면 패드 문자는입니다.

b) X와 Y의 비교 결과는 조합 순서 CS에 의해 주어진다.

c) 조합 순서에 따라 두 문자열은 길이가 다르거 나 다른 문자 시퀀스를 포함하더라도 동일하게 비교 될 수 있습니다. MAX, MIN, DISTINCT, 그룹화 열을 참조하고 UNION, EXCEPT 및 INTERSECT 연산자가 문자열을 참조하는 경우 이러한 동일한 값 세트에서 이러한 조작에 의해 선택된 특정 값은 구현에 따라 다릅니다.

(공포도 추가됨)

이것은 무엇을 의미 하는가? 즉, 문자열을 비교할 때 =연산자는 현재 데이터 정렬 주위의 얇은 래퍼 일뿐입니다. 데이터 정렬은 문자열을 비교하기위한 다양한 규칙이있는 라이브러리입니다. 다음 은 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);
}

이 특정 데이터 정렬은 바이트 단위를 비교하기 위해 발생합니다 (그래서 "이진"이라고 부릅니다. 문자열에 특별한 의미를 부여하지 않습니다). 다른 데이터 정렬은보다 고급 비교를 제공 할 수 있습니다.

예를 들어, 대소 문자를 구분하지 않는 비교를 지원 하는 UTF-8 데이터 정렬 이 있습니다. 코드가 너무 길어서 여기에 붙여 넣을 수는 없지만 해당 링크로 이동하여의 본문을 읽으십시오 my_strnncollsp_utf8mb4(). 이 데이터 정렬은 한 번에 여러 바이트를 처리 할 수 ​​있으며 대소 문자를 구분하지 않는 비교와 같은 다양한 변환을 적용 할 수 있습니다. =연산자는 완전히 정렬의 변덕으로부터 추출된다.

어떻게 LIKE작동합니까?

SQL 표준 § 8.5 방법에 대해 설명 LIKE문자열을 비교 :

<조건 자>

M LIKE P

M을 하위 문자열로 분할하는 경우 다음과 같습니다.

i) M의 서브 스트링은 M의 0 개 이상의 인접한 <문자 표현>의 시퀀스이며 M의 각 <문자 표현>은 정확히 하나의 서브 스트링의 일부입니다.

ii) P의 i 번째 서브 스트링 지정자가 임의의 문자 지정자 인 경우 M의 i 번째 서브 스트링은 임의의 단일 <문자 표현>입니다.

iii) P의 i 번째 서브 스트링 지정자가 임의의 스트링 지정자 인 경우, M의 i 번째 서브 스트링은 0 이상의 <문자 표현>의 임의의 시퀀스이다.

iv) P의 i 번째 서브 스트링 지정자가 임의의 문자 지정자 또는 임의의 스트링 지정자가 아닌 경우, M의 i 번째 서브 스트링은 <like predicate>의 조합 순서에 따라 해당 서브 스트링 지정자와 동일합니다. <space> 문자를 M에 추가하고 하위 문자열 지정자와 길이가 같습니다.

v) M의 서브 스트링 수는 P의 서브 스트링 지정자 수와 같습니다.

(공포도 추가됨)

이것은 꽤 말이 많으므로 세분화합시다. 항목 ii 및 iii은 각각 와일드 카드 _%을 나타냅니다. 경우 P어떤 와일드 카드를 포함하지 않는, 만 항목 IV이 적용됩니다. 이것은 OP가 제기 한 관심사입니다.

이 경우 현재 데이터 정렬 MP사용하여 각 "하위 문자열"(개별 문자)을 각 하위 문자열과 비교합니다 .

결론

결론은 =문자열을 LIKE비교할 때 한 번에 한 문자 를 비교 하면서 전체 문자열을 비교한다는 것입니다. 두 비교는 모두 현재 데이터 정렬을 사용합니다. 이 게시물의 첫 번째 예에서 알 수 있듯이이 차이는 경우에 따라 다른 결과로 이어집니다.

어느 것을 사용해야합니까? 아무도 당신에게 말할 수 없습니다. 사용 사례에 맞는 것을 사용해야합니다. 비교 연산자를 전환하여 조기에 최적화하지 마십시오.


4
"EQUALS는 두 개의 데이터를 바이트 단위로 비교합니다."EQUALS (=) 동작을 COLLATE로 수정하여 문자 대신 문자 클래스를 비교할 수 있기 때문에 지나치게 단순화되고 너무 자주 참이 아닙니다. 예를 볼 dev.mysql.com/doc/refman/5.0/en/charset-collate.html (MySQL의) 또는 sqlmag.com/blog/forcing-collation-where-clause-22-jun-2011 (SQL 서버).
피터 B

11
이것이 정답입니다. 우리는 무엇을 알고 LIKE하지 않습니다,하지만이 답변이 놀랍 사용한다고 설명 LIKE없이 %또는 _존재하는 것은 전혀 없습니다 사용하는 것과 같습니다 =. 귀하의 답변에 수천 건의 찬성 투표를 받으십시오.
rinogo

1
@ mehase 사실이 될 수 없습니다. 내 VARCHAR 필드 값을 포함하는 경우 'AbCdEfG', 그리고 내가 WHERE MyCol = 'abcdefg', 나는 여전히 명확 바이트별로 동일하지 않더라도, 해당 행을 다시 얻을

1
PeterB와 @Kip은 모두 좋은 지적을합니다. 콜 레이션이 이러한 연산자에 어떤 영향을 미치는지 설명하기 위해 답변을 개선했습니다.
Mark E. Haase

2
이것은 더 이상 진실하지 않는 것 : set charset latin1; SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;0을 제공하고 SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;도 0을 제공합니다.
joanq

170

equals (=) 연산자는 "비교 연산자가 두 값의 동등성을 비교합니다"입니다. 즉, SQL 문에서 방정식의 양변이 같지 않으면 참을 리턴하지 않습니다. 예를 들면 다음과 같습니다.

SELECT * FROM Store WHERE Quantity = 200;

LIKE 연산자는 "패턴 일치 비교를 구현하여" "와일드 카드 문자를 포함하는 패턴 문자열과 문자열 값을 일치 시키려고 시도합니다." 예를 들면 다음과 같습니다.

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

LIKE는 일반적으로 문자열에만 사용되며 같음 (더 이상은 빠릅니다). equals 연산자는 와일드 카드 문자를 리터럴 문자로 취급합니다. 반환 된 결과의 차이는 다음과 같습니다.

SELECT * FROM Employees WHERE Name = 'Chris';

SELECT * FROM Employees WHERE Name LIKE 'Chris';

LIKE를 사용하면 일반적으로 패턴 일치로 시간이 더 걸리지 만 동일한 결과를 반환합니다. 하나,

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

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

"="를 사용하면 "Chris %"가 반환 된 결과 만 나오고 LIKE 연산자는 "Chris"로 시작하는 모든 것을 반환하는 다른 결과를 반환합니다.

희망이 도움이됩니다. 좋은 정보는 여기 에서 찾을 수 있습니다 .


108
OP가 LIKE를 사용할 때와 =를 사용할 때를 알고 있다는 인상을 받고 있습니다. 와일드 카드가 없을 때 성능 차이가 있는지 궁금합니다. 이 답변은 간단히 다루지 만이 답변의 95 %는 실제로 관련이 없다고 생각합니다.
무법자 프로그래머

1
매우 사실입니다. 내가 대답했을 때 질문이 같은지 확실하지 않습니다. 그렇다면 성능에 대해 묻는 부분을 놓쳤습니다. 관찰 해 주셔서 감사합니다.
achinda99

9
이 답변은 끔찍합니다. LIKE와 '='는 완전히 별개의 연산자이지만 일부 작은 사례에서 비슷하게 작동합니다. 후손을 위해 여기에 나머지 회신을 읽거나 메모리에 커밋하기 전에 적어도 "mysql like"에 대한 Google을 읽으십시오.
Mark E. Haase 2018 년

3
반면에,이 답변은 내가 가지고 있었고 Google에 대한 질문에 대답했습니다. 때로는 답변이 질문의 제목과 내용에 대해 답변하는 것만으로도 좋습니다.
CorayThan

char과 varchar2를 사용할 때는 기억해야합니다. char과 char을 비교하면 데이터베이스를 비교하기 전에 먼저 첫 번째 'variable'의 길이를 초와 동일하게 변환하십시오. char과 varchar2를 비교하면 데이터베이스는 아무것도하지 않습니다. docs.oracle.com/cd/A64702_01/doc/server.805/a58236/c_char.htm
xild 2013

18

이것은 질문 SQL 'like'vs '='성능 에 대한 또 다른 대답의 복사 / 붙여 넣기입니다 .

mysql 5.5를 사용하는 개인 예제 : 2 개의 테이블, 3 백만 행 중 하나와 1 만 행 중 하나 사이에 내부 조인이있었습니다.

아래와 같이 (와일드 카드 없음) 인덱스에서 like를 사용할 때 약 30 초가 걸렸습니다.

where login like '12345678'

'설명'을 사용하면 다음과 같은 결과를 얻습니다.

여기에 이미지 설명을 입력하십시오

동일한 쿼리에서 '='를 사용하는 경우 약 0.1 초가 걸렸습니다.

where login ='12345678'

'설명'을 사용하면 다음과 같은 결과를 얻습니다.

여기에 이미지 설명을 입력하십시오

보시다시피, like완전히 검색된 인덱스 탐색은 쿼리 시간이 300 배 더 걸렸습니다.


17

LIKE그리고 =다릅니다. LIKE검색어에 사용할 것입니다. 또한 _(단순 문자 와일드 카드) 및 %(다중 문자 와일드 카드)와 같은 와일드 카드도 허용 합니다.

= 정확한 일치를 원하면 더 빠를 것입니다.

이 사이트는 설명합니다 LIKE


11

LIKE와 함께 와일드 카드를 사용할 수있는 가능성과는 다른 한 가지 차이점은 후행 공백입니다. = 연산자는 후행 공백을 무시하지만 LIKE는 그렇지 않습니다.


4
이것은 MySQL 및 MS SQL에 해당하지만 PostgreSQL에는 해당되지 않습니다.
브루노

10

데이터베이스 시스템에 따라 다릅니다.

일반적으로 특수 문자가 없으면 yes, = 및 LIKE가 동일합니다.

그러나 일부 데이터베이스 시스템은 조합 설정을 다른 연산자와 다르게 처리 할 수 ​​있습니다.

예를 들어 MySQL에서 = on strings 비교는 기본적으로 대소 문자를 구분하지 않으므로 특수 문자가없는 LIKE는 동일합니다. 다른 RDBMS의 LIKE는 대소 문자를 구분하지 않지만 =는 그렇지 않습니다.


이 이상한 점에 대한 개요와 같은 것이 있습니까?
Gumbo

9

이 예에서는 varcharcol ''에이 열에 대해 빈 셀이없고 비어 있지 않은 것으로 간주합니다.

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

첫 번째 결과는 0 행 출력이고 두 번째 결과는 전체 목록을 표시합니다. =는 필터와 같은 역할을하는 반면 엄격하게 일치하는 경우입니다. 필터에 기준이 없으면 모든 데이터가 유효합니다.

-그 목적으로 인해 조금 느리게 작동하며 varchar 및 유사한 데이터와 함께 사용하기위한 것입니다.


6

정확히 일치하는 항목을 검색하면 =와 LIKE를 모두 사용할 수 있습니다.

이 경우 "="를 사용하는 것이 조금 더 빠릅니다 (정확한 검색). SQL Server Management Studio에서 동일한 쿼리를 두 번, "="를 사용하여 한 번, "LIKE"를 사용하여 한 번, 그런 다음 "쿼리"/ "실제 실행 계획 포함"을 사용하십시오.

두 개의 쿼리를 실행하면 결과가 두 번 표시되고 두 개의 실제 실행 계획이 표시됩니다. 제 경우에는 50 % 대 50 %로 분할되었지만 "="실행 계획은 "추정 된 하위 트리 비용"이 더 작습니다 (가장 왼쪽의 "SELECT"상자 위로 마우스를 가져 가면 표시됩니다). 큰 차이가 없습니다.

그러나 LIKE 표현식에서 와일드 카드로 검색을 시작하면 검색 성능이 저하됩니다. "LIKE Mill %"검색은 여전히 ​​빠를 수 있습니다. SQL Server는 해당 열에 인덱스가있는 경우이를 사용할 수 있습니다. SQL Server가이 검색을 만족시킬 수있는 유일한 방법은 전체 테이블 스캔을 수행하는 것뿐이므로 "LIKE % expression %"을 검색하는 것은 엄청나게 느립니다. 따라서 당신의 LIKE에주의하십시오!

마크


-1이 아닙니다. 항상 조금 빠르지는 않습니다. % mystring %을 사용하여 열을 색인화하면 몇 배 더 느립니다. 실제로 소금에 걸 맞는 코드 표준은 micky 마우스 데이터베이스보다 큰 경우와 같이 사용하지 않을시기와시기에 대한 엄격한 지침을 갖습니다.
Cruachan

1
나는 모든 경우에 조금 느려질 것이라고 말한 적이 없다-나는 당신이 정확히 일치하는 것을 검색하면 조금 느릴 것이라고 말했다. couse, LIKE로 검색하고 특히 검색 항목의 시작과 끝에 와일드 카드를 사용하는 것은 의심 할 여지없이 느립니다.
marc_s

그리고 네, 동의 합니다-LIKE 사용시기에 관한 명확한 지침이 있어야합니다 (와일드 카드로 검색해야 할 때만). 그러나 다시 한 번 이론 상으로는 이론과 실제에 차이가 없지만 실제로는 .......
marc_s

6

=를 사용하면 런타임에 쿼리를 작성할 때 문자열에서 와일드 카드 및 특수 문자 충돌을 피할 수 있습니다.

이렇게하면 LIKE 절에 빠질 수있는 모든 특수 와일드 카드 문자를 이스케이프 처리하지 않고 의도 한 결과를 생성하지 않으므로 프로그래머의 생활이 더 쉬워집니다. 결국 =는 99 % 사용 사례 시나리오이므로 매번 탈출해야하는 것은 고통 스러울 것입니다.

90 년대에 눈을 굴리다

나는 또한 조금 느리다고 생각하지만 패턴에 와일드 카드가 없다면 그것이 중요하다고 의심합니다.


6

성능에 관한 원래의 질문을 해결하기 위해 인덱스 사용률이 결정 됩니다. 간단한 테이블 스캔이 발생하면 "LIKE"와 "="는 동일합니다 . 인덱스가 포함 되는 경우 LIKE 절이 형성되는 방법에 따라 다릅니다 . 보다 구체적으로, 와일드 카드의 위치는 무엇입니까?


다음을 고려하세요:

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"를 사용할 때 쿼리 계획 작성에 무시할만한 차이가있을 수도 있습니다.


4

와일드 카드 외에 =AND 의 차이점 LIKE은 SQL Server 종류와 열 유형에 따라 다릅니다.

이 예제를 보자 :

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 '
  • MS SQL Server 2012를 사용 LIKE하면 열 유형이 인 경우를 제외하고 비교에서 후행 공백이 무시됩니다 VARCHAR.

  • 사용 의 MySQL 5.5 의 후행 공백은 무시됩니다 =,하지만하지 않는 LIKE, 모두 CHARVARCHAR.

  • 사용 PostgreSQL을 9.1 , 공간이 모두 중요하다 =LIKE사용 VARCHAR,하지만 함께 CHAR(참조 문서 ).

    의 동작 LIKE도와 다릅니다 CHAR.

    위와 동일한 데이터를 사용 CAST하고 열 이름을 명시 적 으로 사용하면 차이가 있습니다 .

    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)

    "CAST both"및 "CAST col"에 대한 행만 반환합니다.


2

LIKE 키워드에는 "성능 가격표"가 첨부되어 있습니다. 즉, 쿼리에 사용할 와일드 카드 문자를 포함 할 수있는 입력 필드가 있으면 입력에 와일드 카드 중 하나가 포함 된 경우에만 LIKE를 사용하는 것이 좋습니다 . 그렇지 않으면 비교와 동일한 표준을 사용하십시오.

친애하는...


1

실제로 그것은 당신이 원하는 쿼리에 달려 있습니다. 정확히 일치하면 =를 사용하십시오. fuzzier match를 의미하는 경우 LIKE를 사용하십시오. 의미하는 바는 일반적으로 코드가 포함 된 좋은 정책입니다.


1

Oracle에서 와일드 카드가없는 'like'는 'equals'와 동일한 결과를 반환하지만 추가 처리가 필요할 수 있습니다. Tom Kyte에 따르면 , 오라클은 리터럴을 사용할 때 와일드 카드가없는 '같은'을 '같음'으로 취급하지만 바인드 변수를 사용할 때는 그렇지 않습니다.


0

=LIKE동일하지;

  1. = 정확한 문자열과 일치
  2. LIKE 와일드 카드 (%)를 포함 할 수있는 문자열과 일치

2
답변이 충분하지 않음

와일드 카드없이 사용할 수 있습니다.이 질문은 동일한 경우에 대한 차이점을 묻습니다.
M-Razavi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.