Tôi tin rằng tiêu đề là tự giải thích. Làm cách nào để bạn tạo cấu trúc bảng trong PostgreSQL để tạo mối quan hệ nhiều-nhiều.
Ví dụ của tôi:
Product(name, price);
Bill(name, date, Products);
Tôi tin rằng tiêu đề là tự giải thích. Làm cách nào để bạn tạo cấu trúc bảng trong PostgreSQL để tạo mối quan hệ nhiều-nhiều.
Ví dụ của tôi:
Product(name, price);
Bill(name, date, Products);
Câu trả lời:
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:
Các n: mối quan hệ m thường được thực hiện bởi một bảng riêng biệt - bill_product
trong trường hợp này.
Tôi đã thêm serial
các cột làm khóa chính thay thế . Trong Postgres 10 trở lên, hãy xem xét một IDENTITY
cột thay thế. Xem:
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 4 byte integer
(hoặc thậm chí 8 byte bigint
) so với 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 date
như 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 các từ nhận dạng 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
thành product
( product_name
hoặc tương tự). Đó là một 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 - điều mà bạn thực hiện rất nhiều trong cơ sở dữ liệu quan hệ - bạn sẽ có nhiều cột có tên "name" 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 a bill
sẽ là gì. bill_id
có lẽ sẽ đủ trong trường hợp này.
price
là kiểu 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ỉ giải quyết các số nguyên, hãy làm điều đó integer
. Ví dụ: bạn có thể tiết kiệm giá dưới dạng Cents .
Các amount
( "Products"
trong câu hỏi của bạn) đi vào bảng liên kết bill_product
và là loại numeric
là tốt. Một lần nữa, integer
nếu bạn đối phó với các số nguyên.
Bạn thấy các khóa ngoại trong bill_product
? Tôi tạo ra cả những thay đổi cascade: ON UPDATE CASCADE
. Nếu một product_id
hoặc bill_id
nên thay đổi, thay đổi sẽ được xếp theo tầng cho tất cả các mục nhập phụ 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 một hóa đơn bị xóa, các chi tiết của nó sẽ chết cùng với nó.
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. product
Thay vào đó, bạn sẽ thêm một cột khác vào để đánh dấu các hàng lỗi thời ("soft-delete").
Tất cả các cột trong ví dụ cơ bản này kết thúc bằng NOT NULL
, vì vậy NULL
giá trị không được phép. (Có, tất cả các cột - cột khóa chính được xác định UNIQUE NOT NULL
tự động.) Đó là 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, dù sao bạn cũng cần hiểu cách NULL
xử lý . Các cột bổ sung có thể cho phép NULL
các giá trị, các hàm và phép nối có thể giới thiệu NULL
các giá trị trong các truy vấn, v.v.
Đọc chương trên 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 chính, điều này giúp cho các truy vấn với các điều kiện trên (các) cột PK 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. Vì PK bill_product
được bật (bill_id, product_id)
trong ví dụ của tôi, bạn có thể muốn thêm một chỉ mục khác vào chỉ product_id
hoặc (product_id, bill_id)
nếu bạn có truy vấn tìm kiếm cho sẵn product_id
và không bill_id
. Xem:
bill_product
? Thông thường nó vẻ nên thích: CREATE INDEX idx_bill_product_id ON booked_rates(bill_id, product_id)
. Thê nay đung không?
bill
. Chúng tôi cần số lượng cho mỗi mục được thêm vào bill_product
.