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

Làm thế nào để triển khai mối quan hệ nhiều-nhiều trong PostgreSQL?

Các câu lệnh SQL DDL (ngôn ngữ định nghĩa dữ liệu) có thể trông giống như sau:

CREATE TABLE product (
  product_id serial PRIMARY KEY  -- implicit primary key constraint
, product    text NOT NULL
, price      numeric NOT NULL DEFAULT 0
);

CREATE TABLE bill (
  bill_id  serial PRIMARY KEY
, bill     text NOT NULL
, billdate date NOT NULL DEFAULT CURRENT_DATE
);

CREATE TABLE bill_product (
  bill_id    int REFERENCES bill (bill_id) ON UPDATE CASCADE ON DELETE CASCADE
, product_id int REFERENCES product (product_id) ON UPDATE CASCADE
, amount     numeric NOT NULL DEFAULT 1
, CONSTRAINT bill_product_pkey PRIMARY KEY (bill_id, product_id)  -- explicit pk
);

Tôi đã thực hiện một vài điều chỉnh:

  • Mối quan hệ n:m thường được triển khai bởi một bảng riêng - bill_product trong trường hợp này.

  • Tôi đã thêm serial cột làm khóa chính thay thế . Trong Postgres 10 trở lên, hãy xem xét một IDENTITY thay vào đó. Xem:

    • Đổi tên bảng một cách an toàn bằng cách sử dụng các cột khóa chính nối tiếp
    • Cột bảng tăng dần tự động
    • https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/

    Tôi thực sự khuyên bạn điều đó, bởi vì tên của một sản phẩm hầu như không phải là duy nhất (không phải là "khóa tự nhiên" tốt). Ngoài ra, việc thực thi tính duy nhất và tham chiếu cột trong khóa ngoại thường rẻ hơn với số nguyên integer (hoặc thậm chí là bigint 8 byte ) so với một chuỗi được lưu trữ dưới dạng text hoặc varchar .

  • Không sử dụng tên của các kiểu dữ liệu cơ bản như date dưới dạng số nhận dạng . Mặc dù điều này là có thể, nhưng nó là một phong cách tồi và dẫn đến các lỗi và thông báo lỗi khó hiểu. Sử dụng số nhận dạng hợp pháp, chữ thường, không được trích dẫn. Không bao giờ sử dụng các từ dành riêng và tránh sử dụng các từ phân biệt chữ hoa và chữ thường được trích dẫn kép nếu bạn có thể.

  • "name" không phải là một cái tên hay. Tôi đã đổi tên cột của bảng product trở thành product (hoặc product_name hoặc tương tự). Đó là quy ước đặt tên tốt hơn . Mặt khác, khi bạn nối một vài bảng trong một truy vấn - bạn thực hiện rất nhiều trong cơ sở dữ liệu quan hệ - bạn kết thúc với nhiều cột có tên là "tên" và phải sử dụng bí danh cột để sắp xếp lộn xộn. Điều đó không hữu ích. Một mẫu chống phổ biến khác sẽ chỉ là "id" làm tên cột.
    Tôi không chắc tên của bill sẽ được. bill_id có lẽ sẽ đủ trong trường hợp này.

  • price thuộc loại dữ liệu numeric để lưu trữ các số phân số chính xác như đã nhập (kiểu chính xác tùy ý thay vì kiểu dấu phẩy động). Nếu bạn chỉ xử lý các số nguyên, hãy đặt integer đó . Ví dụ:bạn có thể tiết kiệm giá dưới dạng Cents .

  • Số tiền amount ("Products" trong câu hỏi của bạn) đi vào bảng liên kết bill_product và thuộc loại numeric cũng. Xin nhắc lại, integer nếu bạn chỉ giải quyết các số nguyên.

  • Bạn thấy khóa ngoại trong bill_product ? Tôi đã tạo cả hai để phân tầng các thay đổi:ON UPDATE CASCADE . Nếu một product_id hoặc bill_id nên thay đổi, thay đổi được tính theo tầng cho tất cả các mục nhập tùy thuộc vào bill_product và không có gì phá vỡ. Đó chỉ là những tài liệu tham khảo không có ý nghĩa riêng.
    Tôi cũng đã sử dụng ON DELETE CASCADE cho bill_id :Nếu hóa đơn bị xóa, các chi tiết của hóa đơn đó sẽ chết theo.
    Không phải như vậy đối với sản phẩm:Bạn không muốn xóa sản phẩm được sử dụng trong hóa đơn. Postgres sẽ báo lỗi nếu bạn cố gắng làm điều này. Bạn sẽ thêm một cột khác vào product để đánh dấu các hàng lỗi thời ("soft-delete") để thay thế.

  • Tất cả các cột trong ví dụ cơ bản này kết thúc là NOT NULL , vì vậy NULL các giá trị không được phép. (Có, tất cả cột - cột khóa chính được xác định UNIQUE NOT NULL tự động.) Đó là bởi vì NULL các giá trị sẽ không có ý nghĩa trong bất kỳ cột nào. Nó làm cho cuộc sống của người mới bắt đầu dễ dàng hơn. Nhưng bạn sẽ không thoát khỏi dễ dàng như vậy, bạn cần hiểu NULL xử lý bằng cách nào. Các cột bổ sung có thể cho phép NULL các giá trị, hàm và phép nối có thể giới thiệu NULL giá trị trong truy vấn, v.v.

  • Đọc chương về CREATE TABLE trong sách hướng dẫn.

  • Khóa chính được triển khai với một chỉ mục duy nhất trên các cột quan trọng, điều này làm cho các truy vấn với các điều kiện trên (các) cột PK trở nên nhanh chóng. Tuy nhiên, trình tự của các cột chính có liên quan trong các khóa nhiều cột. Kể từ khi PK trên bill_product nằm trên (bill_id, product_id) trong ví dụ của tôi, bạn có thể chỉ muốn thêm một chỉ mục khác trên product_id hoặc (product_id, bill_id) nếu bạn có truy vấn tìm kiếm một product_id nhất định và không có bill_id . Xem:

    • Khóa chính tổng hợp PostgreSQL
    • Chỉ số tổng hợp có tốt cho các truy vấn trên trường đầu tiên không?
    • Hoạt động của các chỉ mục trong PostgreSQL
  • Đọc chương về chỉ mục trong sách hướng dẫn.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nhiều kết nối cơ sở dữ liệu trong Rails

  2. Tối ưu hóa truy vấn trong PostgreSQL. GIẢI THÍCH Khái niệm cơ bản - Phần 3

  3. Giới hạn hiệu suất của các giải pháp sao chép hợp lý

  4. Làm cách nào để cài đặt Postgis thành bản cài đặt Keg của [email bảo vệ] bằng Homebrew?

  5. Tạo mật khẩu người dùng postgresql