Giả sử id_pracownika
là PRIMARY KEY
của cái bàn. Hoặc ít nhất được xác định UNIQUE
. (Nếu nó không phải là NOT NULL
, NULL là một trường hợp góc.)
SELECT
hoặc INSERT
Chức năng của bạn là một cách triển khai khác của "SELECT hoặc INSERT" - một biến thể của UPSERT
vấn đề phức tạp hơn khi đối mặt với tải ghi đồng thời hơn có thể tưởng tượng. Xem:
- CHỌN hoặc CHÈN trong một hàm có nguy cơ gặp phải các điều kiện về chủng tộc không?
Với UPSERT trong Postgres 9.5 trở lên
Trong Postgres 9.5 trở lên, hãy sử dụng UPSERT (INSERT ... ON CONFLICT ...
) Chi tiết trong Postgres Wiki. Cú pháp mới này thực hiện một công việc rõ ràng :
CREATE OR REPLACE FUNCTION hire(
_id_pracownika integer
, _imie varchar
, _nazwisko varchar
, _miasto varchar
, _pensja real)
RETURNS text
LANGUAGE plpgsql AS
$func$
BEGIN
INSERT INTO pracownicy
( id_pracownika, imie, nazwisko, miasto, pensja)
VALUES (_id_pracownika,_imie,_nazwisko,_miasto,_pensja);
ON CONFLICT DO NOTHING
RETURNING 'OK';
IF NOT FOUND THEN
RETURN 'JUZ ISTNIEJE';
END IF;
END
$func$;
Các tên cột đủ điều kiện trong bảng để phân biệt khi cần thiết. (Bạn cũng có thể đặt tiền tố cho các tham số hàm với tên hàm, nhưng điều đó thật khó hiểu, dễ dàng.)
Nhưng tên cột trong danh sách đích của một INSERT
có thể không đủ tiêu chuẩn trong bảng. (Dù sao cũng không bao giờ mơ hồ.)
Tốt nhất hãy tránh những điều mơ hồ như vậy trước, như vậy sẽ ít mắc lỗi hơn. Một số (bao gồm cả tôi) thích làm điều đó bằng cách thêm dấu gạch dưới vào trước tất cả các tham số và biến hàm.
Nếu bạn tích cực cần tên cột cũng như tên tham số hàm, một cách để tránh xung đột đặt tên là sử dụng ALIAS
bên trong hàm. Một trong những trường hợp hiếm hoi mà ALIAS
thực sự hữu ích.
Hoặc tham chiếu các tham số hàm theo vị trí thứ tự: $1
cho id_pracownika
trong trường hợp này.
Nếu vẫn không thành công, bạn có thể quyết định điều gì được ưu tiên bằng cách đặt #variable_conflict
. Xem:
- Xung đột đặt tên giữa tham số hàm và kết quả của mệnh đề JOIN với USING
Còn nữa:
-
Có những điều phức tạp đối với
RETURNING
trong một UPSERT. Xem:- Cách sử dụng RETURNING với ON CONFLICT trong PostgreSQL?
-
Các ký tự chuỗi (hằng số văn bản) phải được đặt trong dấu ngoặc kép:'OK', không phải
"OK"
- Chèn văn bản với các dấu ngoặc kép trong PostgreSQL
-
Việc gán các biến tương đối đắt hơn so với các ngôn ngữ lập trình khác. Giữ bài tập ở mức tối thiểu để có hiệu suất tốt nhất trong plpgsql. Thực hiện trực tiếp càng nhiều càng tốt trong các câu lệnh SQL.
-
VOLATILE COST 100
là trình trang trí mặc định cho các chức năng. Không cần phải đánh vần chúng.
Không có UPSERT trong Postgres 9.4 trở lên
...
IF EXISTS (SELECT FROM pracownicy p
WHERE p.id_pracownika = hire.id_pracownika) THEN
RETURN 'JUZ ISTNIEJE';
ELSE
INSERT INTO pracownicy(id_pracownika,imie,nazwisko,miasto,pensja)
VALUES (hire.id_pracownika,hire.imie,hire.nazwisko,hire.miasto,hire.pensja);
RETURN 'OK';
END IF;
...
Trong một EXISTS
biểu thức, SELECT
danh sách không quan trọng. SELECT id_pracownika
, SELECT 1
hoặc thậm chí SELECT 1/0
- tất cả đều giống nhau. Chỉ cần sử dụng SELECT
trống danh sách. Chỉ sự tồn tại của bất kỳ hàng đủ điều kiện nào mới là vấn đề. Xem:
- Điều gì dễ đọc hơn trong các truy vấn phụ EXISTS?