如何执行INSERT / UPDATE到具有FK的链接(Join)表到IDENTITY PKs

时间:2009-12-29 21:58:19

标签: sql sql-server database-design

我是设计自己的数据库的新手。我的项目是订单/产品/库存类型数据,使用SQL Server 2005.在我阅读期间,我遇到了几个客户/订单类型的示例,我决定使用链接表(有时在这里称为联结或联接表)为我Order_Details,因为我在ORDERS和PRODUCTS之间有多对多的关系。

问题是,我不确定我可以使用什么T-SQL结构或语法来插入/更新这个ORDER_DETAILS链接表。这些示例显示您可以单独存储订单详细信息,但我不知道如何使其与Orders和Products表保持同步。我想象某种类型的View会将它们全部连接在一起,其中一个更新会写入所有三个表,但我发现一个View只允许一次更新一个表。我通过在视图上使用“替换OF”触发器尝试了“解决方法”,但我无法弄清楚如何在触发器中编写INSERT语句,因为我必须插入到链接表的FK值是IDENTITY PKs来自父表,因此提前未知。

然后我想也许这可能是在链接表上的FK上的UPDATE CASCADE的情况,并且只是在那里执行我的INSERTS,但它仍然看起来非常令人困惑。我买了一本书,花了很多时间学习设计一个规范化的数据库,但现在我无法弄清楚如何将数据插入其中。

我的计划是稍后用一些DatagridViews等编写VB.NET 2005应用程序,用户可以在其中创建订单,更新产品等。我对应用程序要好得多,但这次我想我宁愿学习设计一个合适的数据库,然后构建可以连接到应用程序控件的视图,即让SQL完成大部分工作。任何人都可以了解维护这些链接表所必需的JOIN / UPDATE / SPROC / VIEW吗?感谢。

为了帮助解释布局,以下是一些架构细节:

ORDERS
----------------
OrderID  PK
OrderDate
EmployeeID fk
CostCenterID fk
etc.


ORDER_DETAILS
-----------------------
OrderID  CPK/fk
ProductID CPK/fk
Qty
OrderDetailComment


PRODUCTS
---------------------
ProductID PK
PartNumber
ProductName
etc.

以下是链接表的当前定义:

CREATE TABLE [Order_Details] (
    [OrderID] INTEGER NOT NULL,
    [ProductID] INTEGER NOT NULL,    
    [Qty] INTEGER NOT NULL,
    [OrderDetailComment] VARCHAR(100),
    CONSTRAINT [CPK_Order_Details] PRIMARY KEY ([OrderID],[ProductID]),
    CONSTRAINT [Order_Details_Orders] FOREIGN KEY ([OrderID]) REFERENCES [Orders] ([OrderID]),
    CONSTRAINT [Order_Details_Products] FOREIGN KEY ([ProductID]) REFERENCES [Products] ([ProductID])    
)
GO

1 个答案:

答案 0 :(得分:1)

您打算使用哪种客户端/数据库访问技术?

如果你使用像Linq-to-SQL或Entity Framework这样的东西 - 你甚至不需要对这些问题绞尽脑汁 - 所有这些都可以很好地为你处理。

基本上,步骤必须是:

  • 插入订单并获取订单ID - 执行此操作的方式数
  • 然后插入所有订单详细信息,假设您有产品ID,现在您还拥有订单ID

要存储订单,您可以:

  • 使用存储过程返回新创建的OrderID(使用INSERT语句中的“OUTPUT”子句,或者查看SCOPE_IDENTITY()
  • 创建一个内联SQL语句,用于执行上述任一操作

所以,要么使用类似的东西(作为直接内联SQL,要么包含在存储过程中 - 您的选择):

INSERT INTO dbo.Orders(OrderDate, EmployeeID, CostCenterID)
OUTPUT Inserted.OrderID
VALUES (........)

或只是做

INSERT INTO dbo.Orders(OrderDate, EmployeeID, CostCenterID)
VALUES (........)

DECLARE @NewOrderID INT
SET @NewOrderID = SCOPE_IDENTITY()

这有帮助吗?

<强>更新
如果要在后续的T-SQL代码中使用新插入的ID,最好的选择是将它们存储到内存中的表变量中 - 如下所示:

DECLARE @NewOrderIDs TABLE (NewOrderID INT)

INSERT INTO dbo.Orders(OrderDate, EmployeeID, CostCenterID)
OUTPUT INSERTED.OrderID INTO @NewOrderIDs 
VALUES  (..........)

INSERT INTO dbo.Orders(OrderDate, EmployeeID, CostCenterID)
OUTPUT INSERTED.OrderID INTO @NewOrderIDs 
VALUES  (..........)

INSERT INTO dbo.Orders(OrderDate, EmployeeID, CostCenterID)
OUTPUT INSERTED.OrderID INTO @NewOrderIDs 
VALUES  (..........)

SELECT * FROM @NewOrderIDs 

如果您只想插入单个订单,获取其新订单ID,然后继续插入订单详细信息,则使用SCOPE_IDENTITY()可能会更容易:

INSERT INTO dbo.Orders(OrderDate, EmployeeID, CostCenterID)
VALUES  (..........)

DECLARE @NewOrderID INT
SET @NewOrderID = SCOPE_IDENTITY()

INSERT INTO dbo.OrderDetails(.....)
........