几个表中的主键和外键关系

时间:2012-11-19 23:48:56

标签: sql foreign-keys primary-key constraints

我对SQL有疑问。我有以下SQL表(简化为易于理解):

客户端(clientId INT PRIMARY KEY)

产品(productId PRIMARY KEY)

订单(orderId PRIMARY,clientId是Client的外键,productId是Product的外键)

我还有一个名为Inventory的表,它应该包含每种产品的库存商品数量。 Inventory的主键称为productId(主键),它引用Order中的外键。 不幸的是,当我尝试添加到Inventory表时,它给出了以下错误:

"The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Order_Iventory1". The conflict occurred in database "GestionInventaire", table "dbo.Inventory", column 'productId'."

我希望Inventory表的主要ID(productId)是Order(productId)中的外键,它来自Product表。

任何帮助表示赞赏!如果需要进一步解释,我会进一步详细说明。

3 个答案:

答案 0 :(得分:1)

基于上面列出的SQL示例(SQL Server):

create table client (
  clientid int not null primary key
)
create table product (
  productid int not null primary key
)
create table [order] (
  orderid int not null primary key,
  clientid int not null foreign key references client (clientid),
  productid int not null foreign key references product (productid)
)

insert into client values (1)
insert into product values (1)

insert into [order] values (1,1,1)  -- should work
insert into [order] values (2,1,2)  -- should fail


create table inventory (
    productid int not null foreign key references product (productid),
    stock int not null default 0
)

insert into inventory values (1,10)  -- worked with no problems

外键引用检查它们在父表中是否存在的值 - 当您看到外键约束错误时,它意味着您尝试插入到具有外键约束的列中的值在父表中不存在引用。

答案 1 :(得分:1)

  

Inventory的主键称为productId(主键),它引用Order中的外键。

为什么呢?对我来说,Inventory中的主键引用Product中的主键会更有意义。

答案 2 :(得分:1)

这取决于您的每种产品的库存信息的复杂程度:

仅存储每种产品的最新库存编号

如果您只是存储每个产品的当前库存号(例如,产品与库存的一对一映射),那么库存就没有必要拥有它自己的表,这将更有意义将数字直接存储在产品表中。

虽然在代码模型中可能存在产品信息和库存数据之间的逻辑划分,但这并不意味着将数据存储在多个表中是一个好主意,除非您处理大量数据并且性能是成为一个问题。即使它存储在一个表中,当您查询并构建模型对象时,仍然可以将数据分成多个对象。

(这并不是说没有合法的情况可能是一个好主意,但除非没有更好的选择,否则我不会考虑它)

为每种产品存储多组库存号

另一方面,如果您想要存储库存水平的历史记录(从产品到库存的一对多映射),那么有一个库存表是有意义的,但我建议给出它是自己的主键,并且具有从productID到Product表的外键。

e.g。库存表包含“InventoryID”(主键),“ProductID”(Product.ProductID的外键)以及存储库存号所需的任何列。

为什么订购表的外键?

无论哪种方式,Inventory.productID都不是Order.productID的外键,因为库存与产品相关,而不是订单(除非您基于数量输入和输出在这种情况下结构会更复杂一点。)