Você não pode remover um produto depois de definido, então adicione um campo Status ao produto que - neste exemplo estou usando um enum, embora possa ser facilmente um INT ou um conjunto de bools (ou seja, Arquivado), eu uso Tabelas de enumeração de parâmetros para isso, mas isso é uma resposta separada.
O mais importante é garantir que a linha da fatura tenha o preço (e descrição) retirado do produto no momento do pedido, para garantir que quaisquer alterações futuras de preço ou alterações no nome do produto não afetem as faturas pré-existentes.
A outra técnica que usei (com bastante sucesso) é introduzir o conceito de superação entidades em um banco de dados - para que o registro original permaneça e uma nova versão seja inserida sempre que os dados forem alterados. Para isso eu adiciono os seguintes campos:
- ID atual
- substituídoPorId
- ID anterior
Isso torna as consultas um pouco mais complicadas - mas especialmente para endereços, é essencial garantir que as faturas permaneçam constantes e que as alterações de endereço não sejam refletidas nas faturas - por exemplo, alterar o nome da empresa não deve alterar as faturas levantadas anteriormente.
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`);