Bạn không thể xóa một sản phẩm khi nó đã được xác định, vì vậy hãy thêm trường Trạng thái vào sản phẩm mà - trong ví dụ này, tôi đang sử dụng enum, mặc dù nó có thể dễ dàng là INT hoặc một bộ bools (tức là Đã lưu trữ), tôi sử dụng Bảng liệt kê tham số cho điều này nhưng đó là một câu trả lời riêng biệt.
Điều quan trọng nhất là đảm bảo rằng dòng hóa đơn có giá (và mô tả) được lấy từ sản phẩm tại thời điểm đặt hàng, để đảm bảo rằng mọi thay đổi về giá trong tương lai hoặc thay đổi tên sản phẩm không ảnh hưởng đến các hóa đơn đã có trước.
Kỹ thuật khác mà tôi đã sử dụng (khá thành công) là giới thiệu khái niệm siêu cưỡng bức các thực thể trong cơ sở dữ liệu - để bản ghi gốc vẫn còn và một phiên bản mới được chèn vào bất cứ khi nào dữ liệu được thay đổi. Để thực hiện việc này, tôi thêm các trường sau:
- currentID
- supersededById
- beforeId
Nó làm cho các truy vấn trở nên cồng kềnh hơn một chút - nhưng đặc biệt là đối với các địa chỉ, điều cần thiết là phải đảm bảo rằng các hóa đơn không đổi và các thay đổi về địa chỉ không được phản ánh trong các hóa đơn - ví dụ:thay đổi tên công ty sẽ không thay đổi các hóa đơn đã tăng trước đây.
CREATE TABLE `Invoice` (
`id` INTEGER NOT NULL AUTO_INCREMENT ,
PRIMARY KEY (`id`)
);
CREATE TABLE `Invoice Item` (
`id` INTEGER NOT NULL AUTO_INCREMENT ,
`desc` VARCHAR(200) NOT NULL ,
`value` DECIMAL(11,3) NOT NULL ,
`quantity` DECIMAL(11,3) NOT NULL ,
`total` DECIMAL(11,3) NOT NULL ,
`fk_id_Invoice` INTEGER NOT NULL ,
`fk_id_Product` INTEGER NOT NULL ,
PRIMARY KEY (`id`)
);
CREATE TABLE `Product` (
`id` INTEGER NOT NULL AUTO_INCREMENT ,
`Price` DECIMAL(11,3) NOT NULL ,
`Name` VARCHAR(200) NOT NULL ,
`Status` ENUM NOT NULL ,
PRIMARY KEY (`id`)
);
ALTER TABLE `Invoice Item` ADD FOREIGN KEY (fk_id_Invoice) REFERENCES `Invoice` (`id`);
ALTER TABLE `Invoice Item` ADD FOREIGN KEY (fk_id_Product) REFERENCES `Product` (`id`);