Chúng tôi tìm thấy chính mình ở bài viết thứ ba trong loạt bài về việc di chuyển Oracle. Lần này, chúng ta xem xét những toán tử kỳ lạ sửa đổi tiêu chí mệnh đề WHERE trong Oracle (+). Giống như mọi thứ khác, PostgreSQL có một giải pháp cho điều đó.
THAM GIA PHẢI
Oracle hỗ trợ và nhiều nhà phát triển sử dụng cú pháp ANSI bên ngoài JOIN bằng cách sử dụng các toán tử cho mệnh đề điều kiện.
Thông thường, nó trông giống như sau:
SELECT *
FROM person, places
WHERE person.id = places.person_id(+)
Mục tiêu của cú pháp này là một phép nối bên ngoài bên phải. Theo thuật ngữ lý thuyết tập hợp, đây là tập hợp con bao gồm tất cả các địa điểm, bất kể người nào.
Kết quả của một mẫu nhỏ sẽ giống như sau:
id | last_name | first_name | id | vị trí | person_id |
---|---|---|---|---|---|
1 | (NULL) | (NULL) | 1 | Dallas | (NULL) |
2 | Roybal | Kirk | 2 | Luân Đôn | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
Cú pháp này không được hỗ trợ trong PostgreSQL.
Để đạt được kết quả tương tự, bạn sẽ sử dụng cú pháp SQL tiêu chuẩn cho các phép nối bên ngoài.
SELECT *
FROM persons
RIGHT JOIN places
ON persons.id = places.person_id;
SQL cũng cung cấp một trạng từ làm rõ OUTER
. Bộ làm rõ này là hoàn toàn tùy chọn, vì bất kỳ RIGHT JOIN
nào theo định nghĩa là OUTER
tham gia.
THAM GIA ĐẦY ĐỦ
Tương tự, việc sử dụng cú pháp Oracle cho một phép nối đầy đủ không hoạt động trong PostgreSQL.
SELECT *
FROM persons, places
WHERE persons.id(+) = places(+);
Mục tiêu của cú pháp này là một danh sách đầy đủ các người và các địa điểm cho dù một người có được liên kết với một địa điểm hay không.
Kết quả như sau:
id | last_name | first_name ** | id | vị trí | person_id |
---|---|---|---|---|---|
1 | (NULL) | (NULL) | 1 | Dallas | (NULL) |
2 | Roybal | Kirk | 2 | Luân Đôn | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
4 | Andrew | Dunstan | (NULL) | (NULL) | (NULL) |
Sử dụng cú pháp PostgreSQL, truy vấn sẽ được viết như vậy:
SELECT *
FROM persons
FULL JOIN places
ON persons.id = places.person_id;
Một lần nữa, OUTER
từ khóa là hoàn toàn tùy chọn.
CROSS JOIN
Một lợi thế khác biệt của phương pháp sử dụng từ khóa thay vì các mối quan hệ ngầm là bạn không thể vô tình tạo ra một sản phẩm chéo.
Cú pháp:
SELECT *
FROM persons
LEFT JOIN places;
Sẽ dẫn đến lỗi:
ERROR: syntax error at or near ";"
Cho biết rằng câu lệnh chưa hoàn thành ở điểm đánh dấu kết thúc dòng “;”.
PostgreSQL sẽ tạo sản phẩm kết hợp chéo bằng cú pháp ANSI.
SELECT *
FROM persons, places;
id | last_name | first_name | id | vị trí | person_id |
---|---|---|---|---|---|
1 | Dunstan | Andrew | 1 | Dallas | (null) |
1 | Dunstan | Andrew | 2 | Luân Đôn | 2 |
1 | Dunstan | Andrew | 3 | Paris | 3 |
1 | Dunstan | Andrew | 4 | Madrid | (null) |
2 | Roybal | Kirk | 1 | Dallas | (null) |
2 | Roybal | Kirk | 2 | Luân Đôn | 2 |
2 | Roybal | Kirk | 3 | Paris | 3 |
2 | Roybal | Kirk | 4 | Madrid | (null) |
3 | Riggs | Simon | 1 | Dallas | (null) |
3 | Riggs | Simon | 2 | Luân Đôn | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
3 | Riggs | Simon | 4 | Madrid | (null) |
6 | Wong | Đánh dấu | 1 | Dallas | (null) |
6 | Wong | Đánh dấu | 2 | Luân Đôn | 2 |
6 | Wong | Đánh dấu | 3 | Paris | 3 |
6 | Wong | Đánh dấu | 4 | Madrid | (null) |
Điều này có nhiều khả năng là lỗi mã hóa hơn là kết quả cố ý.
Để có được chức năng này một cách có chủ đích, bạn nên sử dụng CROSS JOIN
tuyên bố.
SELECT *
FROM persons
CROSS JOIN places;
Do đó, làm cho nó rõ ràng những gì có nghĩa là trong tuyên bố.
THAM GIA TỰ NHIÊN
PostgreSQL hỗ trợ NATURAL JOIN
cú pháp, nhưng hơi bị phản đối.
SELECT *
FROM persons
NATURAL JOIN places;
Điều này tạo ra kết quả sau.
id | last_name | first_name | parent_id | vị trí | person_id |
---|---|---|---|---|---|
1 | Dunstan | Andrew | (null) | Dallas | (null) |
2 | Roybal | Kirk | 1 | Luân Đôn | 2 |
3 | Riggs | Simon | 1 | Paris | 3 |
Tuy nhiên, cú pháp này là một vấn đề. Ví dụ của chúng tôi, cột "id" trong cả hai bảng không liên quan gì đến nhau . Sự liên kết này đã tạo ra một kết quả, nhưng một kết quả có nội dung hoàn toàn không liên quan.
Ngoài ra, bạn có thể có một truy vấn ban đầu hiển thị kết quả chính xác, nhưng các câu lệnh DDL tiếp theo sẽ ảnh hưởng âm thầm.
Cân nhắc:
ALTER TABLE person ADD COLUMN places_id bigint;
ALTER TABLE places ADD COLUMN places_id bigint;
ALTER TABLE person ADD COLUMN person_id bigint;
Bây giờ cột gì là NATURAL JOIN
sử dụng? Các lựa chọn là id, place_id, person_id và tất cả các lựa chọn ở trên. Tôi sẽ để câu trả lời như một bài tập cho người đọc.
Cú pháp này là một quả bom hẹn giờ cho mã của bạn. Chỉ cần không sử dụng nó.
Được rồi, vậy là bạn không bị thuyết phục. Chà, sau đó ít nhất cũng có một số quy ước mã hóa lành mạnh. Đối với bảng mẹ, hãy đặt tên cho cột nhận dạng là “myparenttable_id”. Khi tham chiếu nó từ các quan hệ con, hãy sử dụng cùng một tên, “myparenttable_id”. Không bao giờ đặt tên cho bất kỳ thứ gì là “id”, và không bao giờ tạo tham chiếu đến một cột có tên khác. À, quên nó đi. Đừng làm điều này.
Bạn có thể bị cám dỗ để phân biệt câu đố trước đó bằng cách sử dụng USING
từ khóa. Nó sẽ trông như thế này:
SELECT *
FROM persons
JOIN places
USING (id);
Nhưng USING
từ khóa chỉ có thể tận dụng các kết quả trùng khớp tên chính xác giữa các bảng. Một lần nữa, trong ví dụ của chúng tôi là sai lầm chết người.
Lựa chọn thực tiễn tốt nhất cho PostgreSQL là chỉ cần tránh thiết kế các bảng theo tiêu chuẩn quy ước mã hóa.
Tóm tắt
Các kỹ thuật từ khóa này (so với toán tử) cũng có sẵn trên Oracle. Chúng đa nền tảng hơn và ít mơ hồ hơn. Chỉ điều đó thôi cũng sẽ khiến chúng trở thành những phương pháp hay nhất.
Thêm vào đó, chúng để lộ các lỗi logic khi được sử dụng không đúng cách. Đối với bất kỳ sự phát triển nào trong PostgreSQL, chúng tôi đơn phương khuyên bạn nên sử dụng các từ khóa rõ ràng.