문제

SQL을 사용할 때 다음을 사용하면 어떤 이점이 있습니까? = 안에 WHERE 대신에 절 LIKE?

특별한 연산자 없이, LIKE 그리고 = 똑같지, 그렇지?

도움이 되었습니까?

해결책

다양한 연산자

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 매뉴얼의 이 페이지는 다음과 같습니다. 문자열 비교 함수, 그리고 = 논의되지 않았으며 이는 다음을 의미합니다. = 엄밀히 말하면 문자열 비교 함수는 아닙니다.

어떻게 = 일하다?

그만큼 SQL 표준 § 8.2 방법을 설명합니다 = 문자열을 비교합니다:

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

a) X의 문자 길이가 길이와 같지 않은 경우 Y의 문자에서 더 짧은 문자열은 효과적으로 비교를 위해 다음 사본으로 대체되었습니다. 더 긴 길이로 확장 된 자체 하나 이상의 패드 오른쪽에 있는 연결에 의한 문자열 여기서 패드 문자는 CS를 기반으로 선택됩니다.면 CS에 NO PAD 속성이 있는 경우 패드 문자는 구현 종속 문자는 더 적게 정렬되는 X와 Y의 문자 집합에서 문자 CS의 모든 문자열보다.그렇지 않으면 채움 문자는 .

b) X와 Y의 비교 결과는 Collating Sequence CS에 의해 주어진다.

c) 배열 순서에 따라 두 문자열이 길이가 다르더라도 동일한 것으로 비교하거나 다른 문자 시퀀스를 포함합니다.작업 시 MAX, MIN, DISTINCT, 그룹화 열에 대한 참조 및 UNION, EXCEPT 및 INTERSECT 연산자는 문자를 참조합니다. strings, 이러한 작업에 의해 선택된 특정 값 이러한 동일한 값의 집합은 구현에 따라 다릅니다.

(강조가 추가되었습니다.)

이것은 무엇을 의미 하는가?즉, 문자열을 비교할 때 = 연산자는 현재 데이터 정렬을 둘러싼 얇은 래퍼일 뿐입니다.데이터 정렬은 문자열을 비교하기 위한 다양한 규칙이 있는 라이브러리입니다.다음은 예입니다. 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의 부분 문자열은 0 이상의 연속적인 시퀀스입니다. M의 <문자 표현>과 M의 각 <문자 표현>은 정확히 하나의 하위 문자열의 일부입니다.

ii) P의 i 번째 부분 문자열 지정자가 임의의 경우 문자 지정자, M의 i번째 부분 문자열은 단일 <문자 표현>.

iii) P의 i번째 부분문자열 지정자가 임의의 문자열인 경우 지정자이면, M의 i번째 부분문자열은 0개 이상의 <문자 표현>.

iv) P의 i 번째 부분 문자열 지정자가 임의의 문자 지정자 또는 임의의 문자열 지정자, M의 i 번째 부분 문자열은 해당 부분 문자열과 같습니다. 의 배열 순서에 따른 지정자 <like 술어>를 추가<space>하지 않고 문자를 M으로 설정하고 해당 부분 문자열과 길이가 같습니다. 지정자.

v) M의 부분 문자열의 수는 P의 부분 문자열 지정자입니다.

(강조가 추가되었습니다.)

이것은 꽤 장문이므로 분석해 보겠습니다.항목 ii 및 iii은 와일드카드를 나타냅니다. _ 그리고 %, 각각.만약에 P 와일드카드가 포함되어 있지 않으면 항목 iv만 적용됩니다.이것은 OP가 제기한 관심의 경우입니다.

이 경우에는 각 "하위 문자열"(개별 문자)을 비교합니다. M 각 하위 문자열에 대해 P 현재 데이터 정렬을 사용합니다.

결론

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

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

다른 팁

평등 (=) 연산자는 "비교 연산자는 평등에 대한 두 가지 값을 비교합니다"입니다. 다시 말해, SQL 문에서는 방정식의 양쪽이 동일하지 않으면 TRUE를 반환하지 않습니다. 예를 들어:

SELECT * FROM Store WHERE Quantity = 200;

비슷한 연산자는 "야생 카드 문자가 포함 된 패턴 문자열에 대한 문자열 값을 일치시키려는 패턴 일치 비교"를 구현합니다. 예를 들어:

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

유사하게 일반적으로 문자열과 함께 사용되며 (나는 믿습니다) 더 빠릅니다. 평등 연산자는 야생 카드 문자를 문자 그대로 문자로 취급합니다. 반환 된 결과의 차이는 다음과 같습니다.

SELECT * FROM Employees WHERE Name = 'Chris';

그리고

SELECT * FROM Employees WHERE Name LIKE 'Chris';

같은 결과를 반환하지만, 같은 사용은 일반적으로 패턴 일치와 같은 시간이 더 걸립니다. 하지만,

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

그리고

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

"="를 사용하면 "Chris%"가 반환되고 유사한 연산자가 "Chris"로 시작하는 모든 것을 반환하는 경우 다른 결과를 반환합니다.

도움이되기를 바랍니다. 좋은 정보를 찾을 수 있습니다 여기.

LIKE 그리고 = 다르다. LIKE 검색 쿼리에서 사용할 것입니다. 또한 와일드 카드도 허용합니다 _ (간단한 캐릭터 와일드 카드) 및 % (다중 문자 와일드 카드).

= 정확히 일치하는 경우 사용해야하며 더 빠릅니다.

이 사이트는 설명합니다 LIKE

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

MySQL 5.5를 사용하는 개인적인 예 : 나는 2 개의 테이블, 3 백만 행 중 하나 및 1 만 행 중 하나 사이에 내부 결합이있었습니다.

아래와 같이 인덱스에와 같이 사용하는 경우 (와일드 카드 없음) 약 30 초가 걸렸습니다.

where login like '12345678'

'설명'사용 :

enter image description here

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

where login ='12345678'

'설명'사용 :

enter image description here

보시다시피, like 색인 검색을 완전히 취소하므로 쿼리는 300 배 더 걸렸습니다.

같은 차이점 (좋아요와 함께 와일드 카드를 사용할 가능성과는 별개)은 후행 공간에 있습니다. = 운영자는 후행 공간을 무시하지만 그렇지 않은 것처럼 보입니다.

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

일반적으로 특수 문자가 없으면 그렇습니다. =와 LIKE는 동일합니다.

그러나 일부 데이터베이스 시스템에서는 연산자에 따라 대조 설정을 다르게 처리할 수 있습니다.

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

이 예에서는 varcharcol이 포함하지 않는다고 당연한 것으로 생각합니다. '' 이 열에 대해 빈 셀이 없습니다

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

첫 번째는 0 행 출력이 발생하고 두 번째는 전체 목록을 보여줍니다. = 필터처럼 행동하는 동안 엄격하게 일치하는 경우입니다. 필터에 기준이없는 경우 모든 데이터가 유효합니다.

마찬가지로 - 그 목적으로 인해 약간 느리게 작동하며 Varchar 및 유사한 데이터와 함께 사용하기위한 것입니다.

정확한 일치를 검색하면 둘 다를 사용할 수 있습니다.

이 경우 "="를 사용하는 것은 약간 빠릅니다 (정확한 일치 검색) - SQL Server Management Studio에서 동일한 쿼리를 두 번 사용하여 "="를 사용하고 한 번 "좋아요"를 사용하고 "Like"를 사용하고 일단 "Like"를 사용하고 일단 "Like"를 사용하여 직접 확인할 수 있습니다. 그런 다음 "query" / "실제 실행 계획 포함"을 사용하십시오.

두 쿼리를 실행하면 결과를 두 번, 두 개의 실제 실행 계획을 두 번 볼 수 있습니다. 제 경우에는 50% 대 50% 분할되었지만 "="실행 계획은 더 작은 "추정 하위 트리 비용"을 가지고 있습니다 (왼쪽 "선택"Box 위에 호버링 할 때 표시) - 다시 한번, 실제로는 실제로입니다. 큰 차이가 아닙니다.

그러나 좋아요 표현식에서 와일드 카드로 검색을 시작하면 검색 성능이 다릅니다. 검색 "Like Mill%"는 여전히 매우 빠를 수 있습니다. SQL Server는 해당 열에서 인덱스를 사용할 수 있습니다. SQL Server 가이 검색을 충족시킬 수있는 유일한 방법은 전체 테이블 스캔을 수행하는 것이기 때문에 "Like Expression %"를 검색하는 것은 끔찍하게 느립니다. 그러니 당신의 좋아요를 조심하십시오!

마크

사용 = 실행 시간에 쿼리를 빌드 할 때 스트링에서 와일드 카드 및 특수 문자 충돌을 피하십시오.

이로 인해 프로그래머의 삶은 같은 조항에서 미끄러질 수 있고 의도 된 결과를 생성하지 않는 모든 특별한 와일드 카드 문자를 피할 필요가 없습니다. 결국 = = 99% 사용 사례 시나리오는 매번 탈출 해야하는 것이 고통입니다.

90 년대에 눈을 굴립니다

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

성능에 관한 원래 질문을 해결하기 위해 색인 활용. 간단한 테이블 스캔이 발생하면 "좋아요"및 "="가 동일한. 인덱스가 관련 될 때 의존합니다 같은 절이 어떻게 형성되는지에. 보다 구체적으로, 와일드 카드의 위치는 무엇입니까?


다음을 고려하세요:

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

와일드 카드 외에도 차이가 있습니다 = 그리고 LIKE SQL 서버의 종류와 열 유형에 따라 다릅니다.

이 예를 들어보세요 :

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, 둘 다 CHAR 그리고 VARCHAR.

  • 사용 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)
    

    이것은 "캐스트 둘 다"와 "캐스트 콜"에 대한 행만 반환합니다.

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

친애하는...

실제로 그것은 당신이 쿼리를하고 싶은 일에 귀결됩니다. 정확한 일치를 의미한다면 aude =. 퍼지어 매치를 의미한다면 같은 것을 사용하십시오. 당신이 의미하는 바는 일반적으로 코드와 좋은 정책입니다.

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

= 그리고 LIKE 동일하지 않습니다;

  1. = 정확한 문자열과 일치합니다
  2. LIKE 와일드 카드를 포함 할 수있는 문자열과 일치합니다 (%)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top