“where”절이 대소 문자를 구분하지 않는 SQL 쿼리 (MS SQL Server)를 어떻게 구성합니까?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
사건을 무시하고 결과가 나오길 원합니다
답변
SQL Server 데이터베이스의 기본 구성에서 문자열 비교 는 대소 문자를 구분하지 않습니다. 데이터베이스가이 설정을 재정의하는 경우 (대체 데이터 정렬 사용을 통해) 쿼리에 사용할 데이터 정렬 유형을 지정해야합니다.
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
내가 제공 한 데이터 정렬은 단지 예일뿐입니다. SQL Server 데이터 정렬에 대한 자세한 개요는 여기 에서 찾을 수 있습니다 .
답변
일반적으로 문자열 비교는 대소 문자를 구분하지 않습니다. 데이터베이스가 대소 문자를 구분하도록 구성된 경우 대소 문자를 구분하지 않는 데이터 정렬을 강제로 사용해야합니다.
SELECT balance FROM people WHERE email = 'billg@microsoft.com'
COLLATE SQL_Latin1_General_CP1_CI_AS
답변
다른 곳에서 다른 해결책을 찾았습니다. 즉, 사용
upper(@yourString)
하지만 여기있는 모든 사람들은 SQL Server에서 어쨌든 대소 문자를 무시하기 때문에 중요하지 않다고 말합니다. 나는 우리 데이터베이스가 대소 문자를 구분한다고 확신합니다.
답변
상위 2 개 답변 ( Adam Robinson 및 Andrejs Cainikovs )은 기술적으로 작동한다는 점에서 다소 정확하지만 설명이 잘못되어 많은 경우 오해의 소지가 있습니다. 예를 들어 SQL_Latin1_General_CP1_CI_AS
데이터 정렬은 대부분의 경우 작동하지만 적절한 대 / 소문자를 구분하지 않는 데이터 정렬이라고 가정해서는 안됩니다. 실제로 OP가 대 / 소문자 구분 (또는 바이너리) 데이터 정렬을 사용하여 데이터베이스에서 작동하고 있다는 점을 감안할 때 OP가 너무 많은 설치 (특히 OS에 설치된 모든 데이터)의 기본값 인 데이터 정렬을 사용하지 않는다는 것을 알고 있습니다. 미국 영어를 언어로 사용) : SQL_Latin1_General_CP1_CI_AS
. 물론 OP는를 사용할 수 SQL_Latin1_General_CP1_CS_AS
있지만 작업 할 때VARCHAR
데이터 손실을 초래할 수 있으므로 코드 페이지를 변경하지 않는 것이 중요하며 이는 데이터 정렬의 로케일 / 문화에 의해 제어됩니다 (예 : Latin1_General 대 프랑스어 대 히브리어 등). 아래 9 번 지점을 참조하십시오.
다른 네 가지 대답은 다양한 정도로 잘못되었습니다.
독자가 가장 적절하고 효율적인 선택을 할 수 있도록 여기에서 모든 오해를 명확히 할 것입니다.
-
사용하지 마십시오
UPPER()
. 그것은 완전히 불필요한 추가 작업입니다.COLLATE
절을 사용하십시오 . 두 경우 모두 문자열 비교를 수행해야하지만를 사용하여UPPER()
대문자 매핑이 있는지 확인한 다음 변경해야합니다. 그리고 양쪽에서 이것을해야합니다. 추가는COLLATE
단순히 기본적으로 사용했던 규칙과 다른 규칙 세트를 사용하여 정렬 키를 생성하도록 처리를 지시합니다. 이 테스트 스크립트 (PasteBin) 에서 입증 된 것처럼COLLATE
사용 하는 것이을 사용 하는 것보다 확실히 더 효율적입니다 (또는 해당 단어가 마음에 들면 “성능” ) .UPPER()
@Danny의 답변에 @Ceisc가 언급 한 문제도 있습니다 .
일부 언어의 경우 변환이 왕복하지 않습니다. 즉 LOWER (x)! = LOWER (UPPER (x)).
터키어 대문자 “İ”가 일반적인 예입니다.
-
아니요, 데이터 정렬은 데이터베이스 전체 설정이 아닙니다. 적어도이 컨텍스트에서는 그렇지 않습니다. 데이터베이스 수준의 기본 데이터 정렬이 있으며
COLLATE
절을 지정하지 않는 변경 및 새로 생성 된 열에 대한 기본값으로 사용되지만 (이 일반적인 오해의 원인 일 가능성이 높습니다), 그렇지 않으면 쿼리에 직접 영향을주지 않습니다. 문자열 리터럴 및 변수를 다른 문자열 리터럴 및 변수와 비교하거나 데이터베이스 수준 메타 데이터를 참조합니다. -
아니요, 데이터 정렬은 쿼리별로 이루어지지 않습니다.
-
데이터 정렬은 쿼리가 아닌 조건 자 (예 : 피연산자) 또는 표현식을 기준으로합니다. 그리고 이것은
WHERE
절 뿐만 아니라 전체 쿼리에 대해서도 마찬가지입니다 . 여기에는 JOIN, GROUP BY, ORDER BY, PARTITION BY 등이 포함됩니다. -
아니요, 다음과 같은 이유로
VARBINARY
(예 :)로 변환하지 마십시오convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
.- 이것은 대소 문자를 구분하지 않는 이진 비교입니다 (이 질문이 요구하는 것입니다)
- 이진 비교를 원하면 이진 데이터 정렬을 사용하십시오.
_BIN2
SQL Server 2008 이상을 사용 하는 경우로 끝나는 것을 사용하십시오 . 그렇지 않으면_BIN
. 데이터가NVARCHAR
그렇다면 해당 경우 모두 동일하므로 사용하는 로케일이 중요하지 않으므로Latin1_General_100_BIN2
항상 작동합니다. 데이터가있는 경우VARCHAR
, 당신은 데이터 (예를 들어, 현재 것과 동일한 로케일을 사용해야합니다Latin1_General
,French
,Japanese_XJIS
로케일이 사용되는 코드 페이지를 결정하고, 코드 페이지를 변경하면 데이터 (예 : 데이터 손실)을 변경할 수 있기 때문에, 등). - 크기를 지정하지 않고 가변 길이 데이터 유형을 사용하면 기본 크기에 의존하며 데이터 유형이 사용되는 컨텍스트에 따라 두 가지 다른 기본값이 있습니다. 문자열 유형의 경우 1 또는 30입니다.
CONVERT()
그것 과 함께 사용하면 30 기본값이 사용됩니다. 위험은 문자열이 30 바이트를 초과 할 수있는 경우 자동으로 잘리고이 술어에서 잘못된 결과를 얻을 수 있다는 것입니다. - 대소 문자를 구분하는 비교를 원하더라도 이진 데이터 정렬은 대소 문자를 구분 하지 않습니다 (또 다른 매우 일반적인 오해).
-
아니요,
LIKE
항상 대소 문자를 구분하지는 않습니다. 참조되는 열의 데이터 정렬 또는 변수가 문자열 리터럴과 비교되는 경우 데이터베이스의 데이터 정렬 또는 선택적COLLATE
절을 통해 지정된 데이터 정렬을 사용합니다 . -
LCASE
SQL Server 함수가 아닙니다. Oracle 또는 MySQL 인 것으로 보입니다. 아니면 Visual Basic? -
질문의 컨텍스트는 열을 문자열 리터럴과 비교하기 때문에 인스턴스의 데이터 정렬 (종종 “서버”라고 함)이나 데이터베이스의 데이터 정렬이 여기서 직접적인 영향을 미치지 않습니다 . 데이터 정렬은 각 열마다 저장되며 각 열은 다른 데이터 정렬을 가질 수 있으며 이러한 데이터 정렬은 데이터베이스의 기본 데이터 정렬 또는 인스턴스의 데이터 정렬과 동일 할 필요가 없습니다. 물론 인스턴스 데이터 정렬은 데이터베이스를
COLLATE
만들 때 절이 지정되지 않은 경우 새로 만든 데이터베이스가 기본 데이터 정렬로 사용할 항목의 기본값 입니다. 마찬가지로 데이터베이스의 기본 데이터 정렬은COLLATE
절이 지정되지 않은 경우 변경되거나 새로 생성 된 열이 사용하는 것 입니다. -
그렇지 않으면 열의 데이터 정렬과 동일한 대소 문자를 구분하지 않는 데이터 정렬을 사용해야합니다. 다음 쿼리를 사용하여 열의 데이터 정렬을 찾습니다 (테이블 이름 및 스키마 이름 변경).
SELECT col.* FROM sys.columns col WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName') AND col.[collation_name] IS NOT NULL;
그런 다음 바로 변경할
_CS
수_CI
. 그래서,Latin1_General_100_CS_AS
될 것입니다Latin1_General_100_CI_AS
.열이 이진 데이터 정렬 (
_BIN
또는로 끝남_BIN2
)을 사용하는 경우 다음 쿼리를 사용하여 유사한 데이터 정렬을 찾습니다.SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
예를 들어, 열이를 사용하고 있다고 가정하면 다음을
Japanese_XJIS_100_BIN2
수행하십시오.SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
데이터 정렬, 인코딩 등에 대한 자세한 내용은 다음을 참조하십시오. 데이터 정렬 정보
답변
아니요, 사용 만 LIKE
작동하지 않습니다. LIKE
주어진 패턴과 정확히 일치하는 값을 검색합니다. 이 경우 LIKE
‘someval’이 아닌 ‘sOmeVal’텍스트 만 찾습니다.
실용적인 솔루션은 LCASE()
함수를 사용하는 것입니다. LCASE('sOmeVal')
텍스트의 소문자 문자열 ‘someval’을 가져옵니다. 이 함수를 비교의 양쪽에 사용하면 다음과 같이 작동합니다.
SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
이 명령문은 두 개의 소문자 문자열을 비교하므로 ‘sOmeVal’은 ‘someval’의 다른 모든 표기법과 일치합니다 (예 : ‘Someval’, ‘sOMEVAl’등).
답변
다음과 같이 varbinary로 캐스팅하여 대소 문자를 구분하도록 강제 할 수 있습니다.
SELECT * FROM myTable
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
답변
어떤 데이터베이스에 있습니까? MS SQL Server에서는 데이터베이스 전체의 설정이거나 COLLATE 키워드를 사용하여 쿼리별로 재정의 할 수 있습니다.