2013-06-03 33 views
12

Có thể trong PostgreSQL để tạo ra một ràng buộc duy nhất khó chịu trên một cột ký tự, nhưng không phân biệt chữ hoa chữ thường không?Ràng buộc duy nhất, không phân biệt chữ hoa chữ thường

Giả sử bảng cơ bản sau đây:

CREATE TABLE sample_table ( 
    my_column VARCHAR(100) 
); 

Nếu chế deferrable là không cần thiết, nó cũng đơn giản như việc tạo ra chỉ số duy nhất với chức năng, ví dụ:

CREATE UNIQUE INDEX my_unique_index ON sample_table(UPPER(my_column)); 

thu nhập hoãn lại ràng buộc kiểm tra đòi hỏi phải tạo ràng buộc một cách rõ ràng, ví dụ:

ALTER TABLE sample_table 
ADD CONSTRAINT my_unique_constraint UNIQUE(my_column) 
DEFERRABLE INITIALLY IMMEDIATE; 

Và unfortunatel y không thể sử dụng các hàm tùy ý trong ràng buộc duy nhất.

Một workaround có thể sẽ tạo ra cột bổ sung với nội dung tương tự như my_column, nhưng trường hợp trên, được cập nhật thông qua một kích hoạt sau mỗi lần cập nhật/chèn, sau đó tạo ra một hạn chế duy nhất deferrable trên cột nhân tạo này. Điều này, tuy nhiên, âm thanh như một hack thực sự xấu xí.

Hoặc, có thể sử dụng CREATE CONSTRAINT TRIGGER và kiểm tra thủ công tính độc đáo phân biệt chữ hoa chữ thường (dĩ nhiên, chỉ mục thông thường vẫn cần thiết). Điều này nghe có vẻ một chút quá phức tạp cho một yêu cầu đơn giản (và phổ biến, tôi giả sử) như vậy.

Có cách nào đơn giản và/hoặc thanh lịch hơn xung quanh giới hạn này không?

+0

bạn Postgres phiên bản? –

+0

Hiện tại là 9.1. Tuy nhiên, nếu có một giải pháp tốt đẹp có sẵn trên các phiên bản mới hơn tôi sẽ rất vui khi đọc về nó :) –

+1

Kiểm tra các ràng buộc 'EXCLUDE'. Chúng có thể được thiết lập, hoạt động như trường hợp không nhạy cảm 'UNIQUE'. –

Trả lời

11

Bạn có thể phá vỡ hạn chế bằng cách sử dụng loại đặc biệt citext do mô-đun bổ sung cùng tên cung cấp. Trích dẫn hướng dẫn:

Module citext cung cấp một loại chuỗi ký tự case-insensitive, citext. Về cơ bản, nó gọi nội bộ thấp hơn khi so sánh các giá trị. Nếu không, nó hoạt động gần như chính xác như text.

Nó giải quyết trường hợp của bạn chính xác. Chạy một lần mỗi cơ sở dữ liệu:

CREATE EXTENSION citext; 

Sau đó, bạn có thể:

CREATE TABLE sample_table ( 
    my_column citext 
    ,CONSTRAINT my_unique_constraint UNIQUE(my_column) 
    DEFERRABLE INITIALLY IMMEDIATE 
); 
+0

Tuyệt vời, chính xác những gì tôi muốn trong trường hợp này (vẫn còn hy vọng cho một số giải pháp cho phép chức năng trong các ràng buộc;)). Đối với người dùng Ubuntu - 'citext' nằm trong gói' postgresql-contrib'. –

+1

Tôi không cần phải thêm một phần mở rộng để có một loại chuỗi không phân biệt chữ hoa chữ thường ... postgress nên cung cấp một giải pháp tốt hơn – Leonel

+6

@Leonel: Ý kiến ​​của bạn được ghi nhận hợp lệ. Tuy nhiên, không chắc chắn làm thế nào nó dịch xuống một downvote trên câu trả lời của tôi. Nếu bạn có một vấn đề cụ thể để giải quyết, hãy cân nhắc việc đăng câu hỏi, có nhiều trường hợp khác nhau có thể được giải quyết mà không cần cài đặt phần mở rộng 'citext'.Nhưng không có gì sai khi cài đặt nó và nó thực sự chỉ là vấn đề của 'CREATE EXTENSION citext;'. Module là một phần của phân phối, được duy trì và phát hành bởi cùng một đội và được kiểm tra kỹ lưỡng. Lý do duy nhất nó không có trong bản phát hành cốt lõi là bởi vì hầu hết mọi người không cần nó. Đó là "Postgres", btw, viết tắt của PostgreSQL. –

Các vấn đề liên quan