PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Hàm PostgreSQL cho ID được chèn lần cuối

(tl;dr :goto option 3:INSERT with RETURNING)

Hãy nhớ lại rằng trong postgresql không có khái niệm "id" cho các bảng, chỉ là chuỗi (thường nhưng không nhất thiết được sử dụng làm giá trị mặc định cho khóa chính thay thế, với kiểu giả SERIAL).

Nếu bạn quan tâm đến việc lấy id của một hàng mới được chèn, có một số cách:

Tùy chọn 1:CURRVAL(<sequence name>); .

Ví dụ:

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval('persons_id_seq');

Tên của dãy phải được biết, nó thực sự tùy ý; trong ví dụ này, chúng tôi giả định rằng bảng personsid được tạo bằng SERIAL kiểu giả. Để tránh phụ thuộc vào điều này và để cảm thấy sạch sẽ hơn, bạn có thể sử dụng pg_get_serial_sequence thay thế :

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval(pg_get_serial_sequence('persons','id'));

Lưu ý:currval() chỉ hoạt động sau INSERT (đã thực thi nextval() ), trong cùng một phiên .

Tùy chọn 2:LASTVAL();

Điều này tương tự như trước, chỉ là bạn không cần chỉ định tên trình tự:nó tìm kiếm trình tự được sửa đổi gần đây nhất (luôn bên trong phiên của bạn, lưu ý tương tự như trên).

Cả CURRVALLASTVAL hoàn toàn an toàn đồng thời. Hành vi của trình tự trong PG được thiết kế để các phiên khác nhau sẽ không can thiệp, do đó, không có rủi ro về điều kiện chủng tộc (nếu một phiên khác chèn một hàng khác giữa INSERT và SELECT của tôi, tôi vẫn nhận được giá trị chính xác của mình).

Tuy nhiên họ có một vấn đề tiềm ẩn tinh vi. Nếu cơ sở dữ liệu có một số TRIGGER (hoặc RULE), khi chèn vào persons bảng, thực hiện một số chèn bổ sung trong các bảng khác ... sau đó LASTVAL có thể sẽ cung cấp cho chúng tôi giá trị sai. Sự cố thậm chí có thể xảy ra với CURRVAL , nếu việc chèn thêm được thực hiện cho cùng một persons bảng (điều này ít hơn bình thường nhiều, nhưng rủi ro vẫn tồn tại).

Tùy chọn 3:INSERT với RETURNING

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;

Đây là cách sạch sẽ, hiệu quả và an toàn nhất để lấy id. Nó không có bất kỳ rủi ro nào trước đây.

Mặt hạn chế? Hầu như không có:bạn có thể cần phải sửa đổi cách bạn gọi câu lệnh INSERT của mình (trong trường hợp xấu nhất, có lẽ lớp API hoặc DB của bạn không mong đợi một INSERT trả về một giá trị); nó không phải là SQL tiêu chuẩn (ai quan tâm); nó có sẵn kể từ Postgresql 8.2 (tháng 12 năm 2006 ...)

Kết luận:Nếu bạn có thể, hãy chọn lựa chọn 3. Ở những nơi khác, ưu tiên hơn 1.

Lưu ý:tất cả các phương pháp này đều vô dụng nếu bạn định lấy id được chèn cuối cùng trên toàn cầu (không nhất thiết theo phiên của bạn). Đối với điều này, bạn phải sử dụng đến SELECT max(id) FROM table (tất nhiên, điều này sẽ không đọc các phần chèn chưa được cam kết từ các giao dịch khác).

Ngược lại, bạn nên không bao giờ sử dụng SELECT max(id) FROM table thay vào đó là một trong 3 tùy chọn ở trên, để lấy id vừa được tạo bởi INSERT của bạn vì (ngoài hiệu suất) điều này không an toàn đồng thời:giữa INSERT của bạn và SELECT của bạn một phiên khác có thể đã chèn một bản ghi khác.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lược đồ Django và postgresql

  2. Có gì mới trong PostgreSQL 11

  3. Làm thế nào để lấy một ngày trong năm từ một ngày trong PostgreSQL

  4. dplyr left_join nhỏ hơn, lớn hơn điều kiện

  5. Làm cách nào để chèn một bản ghi có thể cập nhật với cột JSON trong PostgreSQL bằng JOOQ?