PostgreSQL : 대소 문자를 구분하지 않는 쿼리를 만드는 방법


338

PostgreSQL에서 대소 문자를 구분하지 않는 쿼리를 작성하는 방법이 있습니까? 예를 들어 다음 3 개의 쿼리가 동일한 결과를 반환하기를 원합니다.

SELECT id FROM groups where name='administrator'

SELECT id FROM groups where name='ADMINISTRATOR'

SELECT id FROM groups where name='Administrator'

citext가 Postgres 설치와 함께 제공되는 경우 citext 유형을 사용해보십시오. 대소 문자를 구분하지 않는 텍스트
Michael Buen

2
이 질문에 새로 온 사람들을 위해, 공식 postgres 문서에 대한 이 링크 에는 여기에 주어진 모든 답변과 몇 가지 다른 옵션이 포함되어 있습니다.
Parthian Shot

선생님은 @Arun이 만든 답변을 다시 할당하십시오. 적용이 훨씬 덜 복잡하고 문제가 발생하지 않습니다.
zeliboba 2016 년

답변:


451

비교하기 전에 문자열을 소문자로 변환 하려면 LOWER 함수를 사용하십시오 .

이 시도:

SELECT id 
  FROM groups
 WHERE LOWER(name)=LOWER('Administrator')

92
술어 열 (이 경우 "name")에서 LOWER (또는 함수)를 사용하면 인덱스를 더 이상 찾을 수 없게됩니다. 이 테이블이 크거나 자주 쿼리되는 테이블 인 경우 문제가 발생할 수 있습니다. 대소 문자를 구분하지 않는 데이터 정렬, 텍스트 또는 함수 기반 인덱스는 성능을 향상시킵니다.
요르단

108
또는 다음과 같은 색인을 작성하십시오. CREATE INDEX idx_groups_name ON groups lower (name);
Daniel

19
또한 varchar_pattern_ops인덱스가 LIKE 'xxx%'쿼리 와 함께 작동하도록할지 지정 하십시오 ( 예 :) CREATE INDEX ix_groups_name ON groups (lower(name) varchar_pattern_ops).
sayap

10
ILIKE 연산자를 사용하면 (아래의 다른 답변에 나와있는 것처럼) 가장 투표 된 답변이지만 더 간단한 방법입니다.
Ryan

5
여기에 코멘트를 통해가는, 가장 많은 추천 여기에 제안 ILIKE, 그것은 작동합니다 but with slow response. 계산 결과를 기반으로 테이블에 빠르게 액세스하려면 이것을 확인하는 사람은 받아 들일 수있는 대답을 따라야한다고 제안합니다. 자세한 내용은 여기여기를
Afolabi Olaoluwa Akinwumi

230

사용하는 ILIKE대신LIKE

SELECT id FROM groups WHERE name ILIKE 'Administrator'

1
참고 ILIKE봄 부팅에 사용할 때 최대 절전 모드를 지원하지 않습니다.
AnT

@AnT org.hibernate.dialect.PostgreSQL94Dialect와 Spring Boot 2.0.6.RELEASE 와 함께 작동합니다 . 그러나 IntelliJ는 그것에 대해 불평합니다.
Samintha Kaveesh

134

가장 일반적인 방법은 검색 문자열과 데이터를 소문자 또는 대문자로 만드는 것입니다. 그러나 두 가지 문제가 있습니다.

  1. 영어로만 작동하지만 모든 언어로 작동하는 것은 아닙니다. (대부분의 언어로는 지원되지 않을 수도 있습니다.) 모든 소문자에 해당하는 대문자가있는 것은 아닙니다. 모든 대문자에 해당하는 소문자가있는 것은 아닙니다.
  2. lower () 및 upper ()와 같은 함수를 사용하면 순차적 스캔이 제공됩니다. 인덱스를 사용할 수 없습니다. 테스트 시스템에서 lower ()를 사용하면 인덱스를 사용할 수있는 쿼리보다 약 2000 배 더 오래 걸립니다. (테스트 데이터의 행 수는 10 만 개가 조금 넘습니다.)

더 효과적 일 수있는 자주 사용되지 않는 솔루션이 3 개 이상 있습니다.

  1. 대소 문자를 구분하지 않는 데이터 유형의 동작을 모방 한 citext 모듈을 사용하십시오 . 해당 모듈을로드 한 후을 사용하여 대소 문자를 구분하지 않는 색인을 작성할 수 있습니다 CREATE INDEX ON groups (name::citext);. (그러나 아래를 참조하십시오.)
  2. 대소 문자를 구분하지 않는 데이터 정렬을 사용하십시오. 데이터베이스를 초기화 할 때 설정됩니다. 대소 문자를 구분하지 않는 데이터 정렬을 사용하면 클라이언트 코드에서 거의 모든 형식을 받아 들일 수 있으며 여전히 유용한 결과를 반환합니다. 또한 대소 문자를 구분하는 쿼리를 수행 할 수 없다는 의미이기도합니다.
  3. 기능 색인을 작성하십시오. 을 사용하여 소문자 색인을 만듭니다 CREATE INDEX ON groups (LOWER(name));. 쿼리가 좋아하는 당신은 인덱스를 활용할 수 있다는 것을 수행하는 데 SELECT id FROM groups WHERE LOWER(name) = LOWER('ADMINISTRATOR');, 또는 SELECT id FROM groups WHERE LOWER(name) = 'administrator';당신은해야 기억 하지만, LOWER ()를 사용 할 수 있습니다.

citext 모듈은 대소 문자를 구분하지 않는 데이터 형식을 제공하지 않습니다. 대신 각 문자열이 소문자처럼 작동합니다. 즉, lower()위의 3 번과 같이 각 문자열에서 호출 한 것처럼 작동합니다. 프로그래머가 문자열을 소문자로 기억할 필요가 없다는 장점이 있습니다. 그러나 citext를 사용하기 전에 문서에서 "문자열 비교 동작"및 "제한 사항"섹션을 읽어야합니다.


1
# 1에 관하여 : 두 개의 다른 문자열이기 때문에 문제가되지 않습니다. col = 'a' 하고 col = 'b'). # 2에 대하여 : 당신이 말했듯이, 당신은 표현식에 대한 인덱스를 만들 수 있으므로 실제로 문제가되지 않습니다. 그러나 데이터 정렬을 변경하는 것이 가장 좋은 해결책이라는 데 동의합니다.
Vincent Savard

5
PostgreSQL 내장 데이터 정렬이 대소 문자를 구분하지 않는 데이터 정렬을 말해 줄 수 있습니까? 나는 이것을 옵션으로보고 있지만 그물에 Postgres에 대한 대소 문자를 구분하지 않는 데이터 정렬에 대해 아무것도 찾을 수 없습니까?
khorvat

1
@AnupShah : 아니요, 그런 말이 아닙니다. Windows에서 PostgreSQL을 실행하고 있지 않습니다. 9.4 문서는 "모든 플랫폼에서 기본, C 및 POSIX라는 데이터 정렬을 사용할 수 있습니다. 운영 체제 지원에 따라 추가 데이터 정렬을 사용할 수 있습니다." PostgreSQL에서 사용할 수있는 데이터 정렬을 볼 수 있습니다 select * from pg_collation;.
Mike Sherrill 'Cat

1
@Matthieu : 이것은 내가 아는 주제에 대한 가장 좋은 소개 (및주의 사항) 입니다. 1 부 – 텍스트 .
Mike Sherrill 'Cat


95

당신이 사용할 수있는 ILIKE . 즉

SELECT id FROM groups where name ILIKE 'administrator'

정확하고 잘 작동하며 MAC OS X (Mountain Lion)를 사용하고 있습니다.
ADJ

5
이것은 작동하지만 응답 속도가 느립니다. 계산 결과를 기반으로 테이블에 빠르게 액세스하려면 lower함수 를 사용하는 것이 좋습니다 . 더보기 세부
Afolabi Olaoluwa Akinwumi에게

1
@AfolabiOlaoluwaAkinwumi 기본적으로 이것은 알려진 값 을 필터링 하는 것과 반대되는 결과를 검색 하는지 여부에 달려 있습니다 . 후자의 경우, 평등 연산자가 작업 할 수 있도록 단일 균일 사례가 데이터 레벨에서 유지되어야합니다. [개인 추천 타입 코드 값에 대한 상부 파스칼 경우이다]
크리스 Marisic는

53

ILIKE키워드를 읽을 수도 있습니다 . SQL 표준을 준수하지 않더라도 때때로 매우 유용 할 수 있습니다. 자세한 내용은 여기를 참조하십시오 : http://www.postgresql.org/docs/9.2/static/functions-matching.html


9
여기서주의해야 할 것은 악의적 인 사용자 입력입니다. 과 같은 쿼리를 실행하는 경우 email ILIKE 'user-input-email-here'사용자 입력을 피하십시오. 그렇지 않으면 사람들은 %와 같은 문자를 입력 할 수 있습니다.
Matt De Leon

2
@MattDeLeon 안녕하세요. 잘했다. 하지만 난 그냥 사용하는 경우, 당신을 묻고 싶은 ILIKE하고 prepared statements이 나를 보호 할 것입니다 sql injection?
slevin

확실하지 않습니다, 당신이 준비된 문에 이스케이프 문자열을 보내려고한다고 가정합니다.
Matt De Leon

1
"LIKE 대신 키워드 ILIKE를 사용하여 활성 로케일에 따라 대소 문자를 구분하지 않고 일치시킬 수 있습니다. 이는 SQL 표준에는 없지만 PostgreSQL 확장입니다." 9.3의 매력처럼 작동
Aleksey Deryagin

1
ILIKE가보다 느립니다 lower(column_name) like %expression%.
Patryk Imosa

28

POSIX 정규식을 사용할 수도 있습니다.

SELECT id FROM groups where name ~* 'administrator'

SELECT 'asd' ~* 'AsD' 보고 t


1
나는 같은 문제가 있었고 PostgreSQL 데이터베이스에서 대소 문자를 구분하지 않는 검색이 필요했습니다. 사용자 입력 문자열을 정규식으로 변환하는 것에 대해 생각했습니다. 이제 = 또는 LIKE 대신 ~ *를 사용하면 완벽하게 작동했습니다! 나는 새로운 인덱스, 열 또는 무엇이든 만들 필요가 없었습니다. 물론 정규 표현식 검색은 직선 바이트 비교보다 느리지 만 성능에 미치는 영향은 두 데이터 세트 (검색을 위해 소문자 또는 대문자로 처리 한 다음 해당 원본을 검색해야 함)를 처리하는 것보다 훨씬 클 것으로 생각하지 않습니다. 다른 세트의 데이터). 게다가, 이것은 더 깨끗합니다!
사이버 기사

1
좋아,하지만 예를 들어 regexp_matches () 어떻게 처리합니까?
WKT

postgres docs에 따르면 : ~~ 연산자는 LIKE와 같고 ~~ *는 ILIKE에 해당합니다. NOT LIKE 및 NOT ILIKE를 각각 나타내는! ~~ 및! ~~ * 연산자도 있습니다. 이러한 연산자는 모두 PostgreSQL에 따라 다릅니다.
sh4

텍스트에 대괄호가 포함되어 있지만 작동하지 않는 문제에 직면했습니다. "code (LC)"
Oshan Wisumperuma

8

~*INSTR의 기능을 사용하면 성능을 크게 향상시킬 수 있습니다.

SELECT id FROM groups WHERE name ~* 'adm'

OR가 포함 된 이름을 가진 행을 'adm'으로 반환합니다.


1
안녕, 로빈 James Brown의 답변은 이미이 솔루션을 제안했습니다. 또한 제안 된 답변은 어떤 식 으로든 정규식을 사용하지 않습니다.
라파엘
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.