Với điều kiện Sku và ItemNumber sẽ luôn bao hàm các giá trị duy nhất
Tôi cho rằng bạn đã tìm thấy câu trả lời bằng cách khám phá ra rằng, về mặt khái niệm, ItemNumber là một thuộc tính tùy chọn ; tức là, khi bạn xác định rằng nó không áp dụng cho từng trường hợp xuất hiện, được biểu thị bằng các hàng ở mức logic logic của loại thực thể Sản phẩm . Do đó, item_number
cột không nên được khai báo dưới dạng ALTERNATE KEY (AK for brevity) trong product
bảng, như bạn đã chỉ ra một cách đúng đắn.
Về mặt này, Kịch bản B của bạn khá hợp lý, vì công thức ở cấp độ khái niệm sau đây thể hiện:
- Một sản phẩm có thể có hoặc không có số mặt hàng .
Nói cách khác, có một tỷ lệ cardinality từ 1 đến 0 hoặc 1 (1: 0/1) giữa Product và ItemNumber .
Sau đó, vâng, bạn nên giới thiệu một bảng mới để xử lý cột tùy chọn và tôi đồng ý rằng đó product_item_number
là một tên rất mô tả cho nó. Bảng này phải được sku
ràng buộc là KHÓA CHÍNH (PK) của nó, để đảm bảo rằng không có nhiều hơn một hàng có cùng sku
giá trị được chèn vào nó, giống như bạn đã làm.
Điều quan trọng nữa là phải đề cập đến điều đó product_item_number.sku
cũng nên bị ràng buộc như là một NGOẠI TỆ (FK) làm tham chiếu đến product.sku
.
Dưới đây là một thiết kế mức logic SQL-DDL mẫu minh họa các đề xuất trước đó:
-- You should determine which are the most fitting
-- data types and sizes for all your table columns
-- depending on your business context characteristics.
-- Also, you should make accurate tests to define
-- the most convenient INDEXing strategies.
CREATE TABLE product (
sku TEXT NOT NULL,
name TEXT NOT NULL,
price NUMERIC NOT NULL,
quantity NUMERIC NOT NULL,
--
CONSTRAINT product_PK PRIMARY KEY (sku),
CONSTRAINT product_AK UNIQUE (name), -- AK.
CONSTRAINT valid_price_CK CHECK (price > 0),
CONSTRAINT valid_quantity_CK CHECK (quantity > 0)
);
CREATE TABLE product_item_number (
sku TEXT NOT NULL, -- To be constrained as PK and FK to ensure the 1:0/1 correspondence ratio between the relevant rows.
item_number TEXT NOT NULL,
--
CONSTRAINT product_item_number_PK PRIMARY KEY (sku),
CONSTRAINT product_item_number_AK UNIQUE (item_number), -- In this context, ‘item_number’ is an AK.
CONSTRAINT product_item_number_TO_product_FK FOREIGN KEY (sku)
REFERENCES product (sku)
);
Đã thử nghiệm trên PostgreSQL 11 trong db <> fiddle này .
Ngoài ra, có một công thức khái niệm khác hướng dẫn trong việc định hình thiết kế cơ sở dữ liệu được trình bày ở trên:
- Nếu nó tồn tại, ItemNumber của sản phẩm phải là duy nhất.
Vì vậy, trong đó item_number
cột thực sự phải được khai báo là AK ở ngay đó, trong product_item_number
bảng, bởi vì cột đã nói chỉ yêu cầu bảo vệ tính duy nhất khi giá trị thích hợp được cung cấp, do đó các ràng buộc UNIQUE và KHÔNG NULL phải được cấu hình tương ứng.
Thiếu giá trị và phiên dịch thế giới khép kín
Sự sắp xếp SQL-DDL hợp lý được mô tả trước đây là một ví dụ về cách tiếp cận quan hệ để xử lý các giá trị bị thiếu, mặc dù nó không phải là cách phổ biến nhất của Wapor thông thường. Cách tiếp cận này có liên quan đến Phiên dịch thế giới khép kín Thông qua vị trí này, (a) thông tin được ghi trong cơ sở dữ liệu luôn được coi là đúng và (b) thông tin không được ghi trong đó luôn luôn được coi là sai . Theo cách này, người ta chỉ giữ lại những sự thật được biết đến .
Trong kịch bản kinh doanh hiện tại, khi người dùng cung cấp tất cả các điểm dữ liệu được bao gồm trong product
bảng, bạn phải XÁC NHẬN hàng tương ứng và nếu, và chỉ khi, người dùng tạo item_number
dữ liệu có sẵn, bạn cũng phải CHỌN product_item_number
đối tác. Trong trường hợp item_number
giá trị không xác định hoặc đơn giản là nó không áp dụng, bạn không XÁC NHẬN một product_item_number
hàng và đó là giá trị đó.
Với phương pháp này, bạn tránh giữ các dấu / đánh dấu NULL trong các bảng cơ sở của mình và các hậu quả ở mức logic mà tôi sẽ trình bày chi tiết trong phần tiếp theo, nhưng bạn nên biết rằng đây là một chủ đề gây tranh cãi trong một phạm vi quản trị cơ sở dữ liệu. Về điểm này, bạn có thể tìm thấy giá trị các câu trả lời cho câu hỏi Stack Overflow có tên:
Quá trình hành động phổ biến
Tuy nhiên, tôi đoán rằng tiến trình phổ biến của trò chơi phổ biến của người Viking sẽ là có một product
bảng duy nhất bao gồm item_number
cột, lần lượt, sẽ được đặt là NULLable, đồng thời, được xác định bằng một ràng buộc KHÔNG GIỚI HẠN. Theo cách tôi thấy, cách tiếp cận này sẽ làm cho cơ sở dữ liệu của bạn và các thao tác thao tác dữ liệu hiện hành trở nên kém thanh lịch (như được hiển thị, ví dụ, trong câu trả lời Stack Overflow nổi bật này ), nhưng đó là một khả năng.
Xem các tuyên bố DDL liên tiếp minh họa cho quá trình hành động này:
CREATE TABLE product (
sku TEXT NOT NULL,
name TEXT NOT NULL,
price NUMERIC NOT NULL,
quantity NUMERIC NOT NULL,
item_number TEXT NULL, -- Accepting NULL marks.
--
CONSTRAINT product_PK PRIMARY KEY (sku),
CONSTRAINT product_AK1 UNIQUE (name), -- AK.
CONSTRAINT product_AK2 UNIQUE (item_number), -- Being ‘NULLable’, this is not an AK.
CONSTRAINT valid_price_CK CHECK (price > 0),
CONSTRAINT valid_quantity_CK CHECK (quantity > 0)
);
Đã thử nghiệm trên PostgreSQL 11 trong db <> fiddle này .
Vì vậy, khi đã thiết lập item_number
như một cột có thể chứa NULL, không đúng khi nói, về mặt logic, đó là một AK. Hơn nữa, bạn sẽ lưu trữ các dấu NULL mơ hồ mà không phải là giá trị, cho dù tài liệu PostgreQuery có gắn nhãn theo cách đó hay không, do đó có thể lập luận rằng bảng sẽ không thể hiện đúng về một quan hệ toán học và quy tắc chuẩn hóa phù hợp được áp dụng cho nó.
Vì NULL chỉ ra rằng giá trị cột là (1) không xác định hoặc (2) không thể áp dụng , nên không thể nói chính xác rằng dấu đã nói thuộc về item_number
miền giá trị hợp lệ. Như bạn đã biết, loại nhãn hiệu này nói lên điều gì đó về trạng thái của người Bỉ về một giá trị thực, nhưng bản thân nó không phải là một giá trị và, tự nhiên, nó không hành xử như vậy, và thật đáng để đề cập đến Các NULL hoạt động khác nhau trên các hệ thống quản lý cơ sở dữ liệu SQL riêng biệt, thậm chí trên các phiên bản khác nhau của cùng một hệ thống quản lý cơ sở dữ liệu.
Sau đó, nếu (i) miền của các giá trị của một cột nhất định và (ii) ý nghĩa mà cột nói đó mang lại không hoàn toàn rõ ràng do kết quả của việc bao gồm các NULL:
Mặc dù cả hai đều có lý thuyết và thực tế về thao túng dữ liệu, ngụ ý về việc lưu giữ các dấu NULL trong cơ sở dữ liệu, đây là cách tiếp cận để xử lý dữ liệu bị thiếu mà bạn sẽ tìm thấy trong phần lớn các cơ sở dữ liệu được xây dựng trên nền tảng SQL, vì nó cho phép gắn các cột cho các giá trị tùy chọn vào các bảng cơ sở có ý nghĩa và, như một hiệu ứng, xóa bỏ việc tạo ra (a) một bảng bổ sung và (b) các nhiệm vụ liên quan.
Quyết định
Tôi đã trình bày hai phương án để bạn có thể tự xác định xem cái nào phù hợp hơn để đạt được mục tiêu của mình.
Giả sử rằng các Sku và ItemNumber giá trị cuối cùng có thể được nhân đôi
Có một số điểm trong câu hỏi của bạn thu hút sự chú ý của tôi theo một cách cụ thể, vì vậy tôi đã liệt kê chúng:
Đôi khi (có thể 3% đến 5% thời gian), item_number thực sự bằng SKU. Đó là, một trong những nhà cung cấp của tôi đặc biệt gắn liền với các sản phẩm của họ, điều mà tôi nghi ngờ không phải là một SKU duy nhất trên toàn cầu, được đặt theo số mặt hàng của họ.
[V]] có thể có trường hợp nhà cung cấp tái chế số danh mục với một sku khác nhau (có thể?), Hoặc tình huống hai nhà sản xuất đều tạo ra "d57-red" hoặc đại loại như thế. Trong trường hợp đó, tôi nghĩ rằng tôi phải lập trình tiền tố xúc phạm item_numbers với tên nhà sản xuất hoặc đại loại như thế.
Một sku sẽ luôn là duy nhất trong miền của tôi (Một lượng nhỏ SKU do nhà cung cấp duy nhất không cung cấp trên toàn cầu không có khả năng va chạm).
Những điểm đó có thể có tác động đáng chú ý vì dường như chúng gợi ý rằng:
Các giá trị ItemNumber cuối cùng có thể trở thành trùng lặp và khi điều đó xảy ra, bạn có thể đánh giá việc kết hợp hai mẩu thông tin khác nhau mang ý nghĩa khác nhau trong cùng một cột.
Có thể, sau tất cả, các giá trị Sku có thể được lặp lại (ngay cả khi đó là một lượng nhỏ các trường hợp Sku lặp lại ).
Về vấn đề này, cần lưu ý rằng hai mục tiêu tối quan trọng của bài tập mô hình hóa dữ liệu là (1) xác định từng mốc dữ liệu quan trọng và (2) ngăn chặn việc giữ lại nhiều hơn một trong số chúng trong cùng một cột. Các yếu tố này, ví dụ, tạo điều kiện cho việc phân định cấu trúc cơ sở dữ liệu ổn định và linh hoạt và hỗ trợ trong việc tránh thông tin trùng lặp. Giúp làm gì để duy trì các giá trị dữ liệu phù hợp với quy tắc kinh doanh, thông qua các ràng buộc tương ứng.
Thay thế để xử lý các bản sao Sku : Giới thiệu manufacturer
bảng cho kịch bản
Do đó, với điều kiện có thể chia sẻ cùng một giá trị Sku giữa các Nhà sản xuất khác nhau , bạn có thể sử dụng ràng buộc PK tổng hợp trong product
bảng và nó sẽ được tạo thành từ (i) cột PK của nhà sản xuất và (ii) sku
. Ví dụ:
CREATE TABLE manufacturer (
manufacturer_number INTEGER NOT NULL, -- This could be something more meaningful, e.g., ‘manufacturer_code’.
name TEXT NOT NULL,
--
CONSTRAINT manufacturer_PK PRIMARY KEY (manufacturer_number),
CONSTRAINT manufacturer_AK UNIQUE (name) -- AK.
);
CREATE TABLE product (
manufacturer_number INTEGER NOT NULL,
sku TEXT NOT NULL,
name TEXT NOT NULL,
price NUMERIC NOT NULL,
quantity NUMERIC NOT NULL,
--
CONSTRAINT product_PK PRIMARY KEY (manufacturer_number, sku), -- Composite PK.
CONSTRAINT product_AK UNIQUE (name), -- AK.
CONSTRAINT product_TO_manufacturer_FK FOREIGN KEY (manufacturer_number)
REFERENCES manufacturer (manufacturer_number),
CONSTRAINT valid_price_CK CHECK (price > 0),
CONSTRAINT valid_quantity_CK CHECK (quantity > 0)
);
Và, nếu ItemNumber yêu cầu bảo toàn tính duy nhất khi áp dụng , thì product_item_number
bảng có thể được cấu trúc như sau:
CREATE TABLE product_item_number (
manufacturer_number INTEGER NOT NULL,
sku TEXT NOT NULL,
item_number TEXT NOT NULL,
--
CONSTRAINT product_item_number_PK PRIMARY KEY (manufacturer_number, sku), -- Composite PK.
CONSTRAINT product_item_number_AK UNIQUE (item_number), -- AK.
CONSTRAINT product_item_number_TO_product_FK FOREIGN KEY (manufacturer_number, sku)
REFERENCES product (manufacturer_number, sku)
);
Đã thử nghiệm trên PostgreSQL 11 trong db <> fiddle này .
Trong trường hợp đó ItemNumber nào không yêu cầu bản sao ngăn chặn, bạn chỉ cần loại bỏ các hạn chế UNIQUE tuyên bố cho một cột như vậy, như thể hiện trong các câu lệnh DDL tiếp theo:
CREATE TABLE product_item_number (
manufacturer_number INTEGER NOT NULL,
sku TEXT NOT NULL,
item_number TEXT NOT NULL, -- In this case, ‘item_number’ does not require a UNIQUE constraint.
--
CONSTRAINT product_item_number_PK PRIMARY KEY (manufacturer_number, sku), -- Composite PK.
CONSTRAINT product_item_number_TO_product_FK FOREIGN KEY (manufacturer_number, sku)
REFERENCES product (manufacturer_number, sku)
);
Mặt khác, giả rằng ItemNumber không thực sự đòi hỏi tránh các giá trị lặp đi lặp lại độc quyền liên quan đến các liên Hãng sản xuất , bạn có thể thiết lập một UNIQUE chế tổng hợp trong đó sẽ bao gồm manufacturer_number
và item_number
, như đã chứng minh trong các dòng mã bên dưới:
CREATE TABLE product_item_number (
manufacturer_number INTEGER NOT NULL,
sku TEXT NOT NULL,
item_number TEXT NOT NULL,
--
CONSTRAINT product_item_number_PK PRIMARY KEY (manufacturer_number, sku), -- Composite PK.
CONSTRAINT product_item_number_AK UNIQUE (manufacturer_number, item_number), -- Composite AK.
CONSTRAINT product_item_number_TO_product_FK FOREIGN KEY (manufacturer_number, sku) -- Composite FK.
REFERENCES product (manufacturer_number, sku)
);
Khi các giá trị Sku luôn là duy nhất nhưng một giá trị ItemNumber cụ thể có thể được chia sẻ giữa các Nhà sản xuất riêng biệt
Nếu bạn có thể đảm bảo rằng Product.Sku sẽ không bao giờ có nghĩa bản sao nhưng một ItemNumber có thể được sử dụng bởi riêng biệt nhà sản xuất , bạn có thể cấu hình cơ sở dữ liệu của bạn như tiếp xúc ở đây:
CREATE TABLE manufacturer (
manufacturer_number INTEGER NOT NULL,
name TEXT NOT NULL,
--
CONSTRAINT manufacturer_PK PRIMARY KEY (manufacturer_number),
CONSTRAINT manufacturer_AK UNIQUE (name) -- AK.
);
CREATE TABLE product (
sku TEXT NOT NULL,
name TEXT NOT NULL,
price NUMERIC NOT NULL,
quantity NUMERIC NOT NULL,
--
CONSTRAINT product_PK PRIMARY KEY (sku),
CONSTRAINT product_AK UNIQUE (name), -- AK.
CONSTRAINT valid_price_CK CHECK (price > 0),
CONSTRAINT valid_quantity_CK CHECK (quantity > 0)
);
CREATE TABLE product_item_number (
sku TEXT NOT NULL,
manufacturer_number INTEGER NOT NULL,
item_number TEXT NOT NULL,
--
CONSTRAINT product_item_number_PK PRIMARY KEY (sku, manufacturer_number),
CONSTRAINT product_item_number_AK UNIQUE (manufacturer_number, item_number), -- In this context, ‘manufacturer_number’ and ‘item_number’ compose an AK.
CONSTRAINT product_item_number_TO_product_FK FOREIGN KEY (sku)
REFERENCES product (sku),
CONSTRAINT product_item_number_TO_manufacturer_FK FOREIGN KEY (manufacturer_number)
REFERENCES manufacturer (manufacturer_number)
);
Đã thử nghiệm trên PostgreSQL 11 trong db <> fiddle này .
Cân nhắc cấp độ vật lý
Chúng tôi đã không thảo luận về loại và kích thước chính xác của product.sku
cột nhưng, nếu đó là số lượng lớn về mặt byte, thì nó có thể làm giảm tốc độ truy xuất dữ liệu của hệ thống của bạn đối với các khía cạnh của mức độ trừu tượng hóa, được liên kết với, ví dụ, kích thước của các chỉ mục và không gian đĩa sử dụng.
Theo cách này, bạn có thể muốn đánh giá sự kết hợp của cột INTEGER có thể cung cấp phản hồi nhanh hơn so với một văn bản có thể nặng nề của một văn bản, tất cả phụ thuộc vào các tính năng chính xác của các cột được so sánh. Nó cũng có thể là product_number
, như mong đợi, sẽ đại diện cho một giá trị số trong một chuỗi đứng cho tập hợp được ghi lại products
.
Một sắp xếp kho lưu trữ kết hợp yếu tố mới này là một trong đó:
CREATE TABLE product (
product_number INTEGER NOT NULL,
sku TEXT NOT NULL,
name TEXT NOT NULL,
price NUMERIC NOT NULL,
quantity NUMERIC NOT NULL,
--
CONSTRAINT product_PK PRIMARY KEY (sku),
CONSTRAINT product_AK UNIQUE (name), -- AK.
CONSTRAINT valid_price_CK CHECK (price > 0),
CONSTRAINT valid_quantity_CK CHECK (quantity > 0)
);
CREATE TABLE product_item_number
(
product_number INTEGER NOT NULL,
item_number TEXT NOT NULL,
--
CONSTRAINT product_item_number_PK PRIMARY KEY (product_number),
CONSTRAINT product_item_number_AK UNIQUE (item_number), -- AK.
CONSTRAINT product_item_number_TO_product_FK FOREIGN KEY (product_number)
REFERENCES product (product_number)
);
Tôi đặc biệt khuyên bạn nên thực hiện các phiên kiểm tra đáng kể với tải dữ liệu đáng kể để quyết định khóa nào thuận tiện hơn khi nói tiếng Tây Ban Nha, luôn luôn tính đến các tính năng cơ sở dữ liệu tổng thể (số cột của tất cả các bảng, loại và kích cỡ của các cột, các ràng buộc và các chỉ mục cơ bản, v.v.).
Kịch bản tương tự
Môi trường kinh doanh quan tâm của bạn thể hiện sự tương đồng nhất định với kịch bản được xử lý trong các bài đăng này , vì vậy bạn có thể thấy sự liên quan của một số điểm được thảo luận.