Nói chung, tôi đồng ý với lời khuyên của @ kgrittn. Tiếp tục.
Nhưng để giải quyết câu hỏi cơ bản của bạn về concat()
:Hàm mới concat()
rất hữu ích nếu bạn cần xử lý giá trị null - và null không bị loại trừ trong câu hỏi của bạn cũng như trong câu mà bạn đề cập đến.
Nếu bạn có thể loại trừ các giá trị rỗng, toán tử nối cũ tốt (chuẩn SQL) ||
vẫn là lựa chọn tốt nhất và câu trả lời của @luis rất ổn:
SELECT col_a || col_b;
Nếu một trong các cột của bạn có thể là rỗng, kết quả sẽ là rỗng trong trường hợp đó. Bạn có thể bảo vệ bằng COALESCE
:
SELECT COALESCE(col_a, '') || COALESCE(col_b, '');
Nhưng điều đó trở nên tẻ nhạt nhanh chóng với nhiều tranh luận hơn. Đó là nơi concat()
đến, mà không bao giờ trả về null, ngay cả khi tất cả các đối số là rỗng. Theo tài liệu:
Đối số NULL bị bỏ qua.
SELECT concat(col_a, col_b);
Trường hợp góc còn lại cho cả hai lựa chọn thay thế là nơi tất cả cột đầu vào rỗng trong trường hợp đó, chúng tôi vẫn nhận được một chuỗi rỗng ''
, nhưng người ta có thể muốn null thay vào đó (ít nhất là tôi muốn). Một cách khả thi:
SELECT CASE
WHEN col_a IS NULL THEN col_b
WHEN col_b IS NULL THEN col_a
ELSE col_a || col_b
END;
Điều này trở nên phức tạp hơn với nhiều cột hơn một cách nhanh chóng. Một lần nữa, hãy sử dụng concat()
nhưng thêm một séc cho điều kiện đặc biệt:
SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
ELSE concat(col_a, col_b) END;
Tính năng này hoạt động như thế nào?
(col_a, col_b)
là ký hiệu viết tắt cho biểu thức loại hàng ROW (col_a, col_b)
. Và loại hàng chỉ rỗng nếu tất cả cột rỗng. Giải thích chi tiết:
- Ràng buộc NOT NULL trên một tập hợp các cột
Ngoài ra, hãy sử dụng concat_ws()
để thêm dấu phân cách giữa các phần tử (ws
cho "có dấu phân tách").
Một biểu hiện giống như trong câu trả lời của Kevin:
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
thật tẻ nhạt khi chuẩn bị cho các giá trị null trong PostgreSQL 8.3 (không có concat()
). Một cách (trong nhiều cách):
SELECT COALESCE(
CASE
WHEN $1.zipcode IS NULL THEN $1.city
WHEN $1.city IS NULL THEN $1.zipcode
ELSE $1.zipcode || ' - ' || $1.city
END, '')
|| COALESCE(', ' || $1.state, '');
Độ biến động của hàm chỉ là STABLE
concat()
và concat_ws()
STABLE
các chức năng, không phải IMMUTABLE
vì chúng có thể gọi các hàm đầu ra kiểu dữ liệu (như timestamptz_out
) tùy thuộc vào cài đặt ngôn ngữ.
Giải thích của Tom Lane.
Điều này cấm sử dụng trực tiếp chúng trong các biểu thức chỉ mục. Nếu bạn biết rằng kết quả thực sự là không thay đổi trong trường hợp của bạn, bạn có thể giải quyết vấn đề này với IMMUTABLE
trình bao bọc chức năng. Ví dụ ở đây:
- PostgreSQL có hỗ trợ các ảnh ghép "không nhạy cảm với trọng âm" không?