主子表最常见的大概就是用在进销存、MRP、ERP里面,比如一张销售订单,订单Order(ID,OrderDate),订单明细OrderDetail(OrderID, ProductID, Num,Price)这个大概就是最简单的主子表了,两个表通过ID与OrderID建立关联,这里主键ID是自增的INT类型,OrderID是表OrderDetail的外键。当然,键的选择方法很多,现在我们选择的是在sql里面最简单的方法。
对于这样的表结构,我们最常见的问题就是保存的时候怎样处理键值的问题,因为两个表关联非常的紧密,我们进行保存的时候需要把它们放在一个事务里面,这时问题就会出现,Order表中的ID是自动增长型的字段。现在需要我们录入一张订单,包括在Order表中插入一条记录以及在OrderDetail表中插入若干条记录。因为Order表中的ID是自动增长型的字段,那么我们在记录正式插入到数据库之前无法事先得知它的取值,只有在更新后才能知道数据库为它分配的是什么值,然后再用这个ID作为OrderDetail表的OrderID的值,最后更新OderDetail表。但是,为了确保数据的一致性,Order与OrderDetail在更新时必须在事务保护下同时进行,即确保两表同时更行成功,这个就会有点困扰。
解决这类问题常见的主要有两类方法:
一种是微软在网上书店里使用的方法,使用了四个存储过程。改装一下,使之符合现在的例子
--存储过程一
CREATE PROCEDURE InsertOrder
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@Id INT = NULL OUTPUT,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@OrderDate DATETIME = NULL,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@ProductIDList NVARCHAR(4000) = NULL,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@NumList NVARCHAR(4000) = NULL,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@PriceList NVARCHAR(4000) = NULL
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
AS
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
SET NOCOUNT ON
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
SET XACT_ABORT ON
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
BEGIN TRANSACTION
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
--插入主表
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
INSERT Orders(OrderDate) select @OrderDate
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
SELECT @Id = @@IDENTITY
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
-- 插入子表
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
IF @ProductIDList IS NOT NULL
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
EXECUTE InsertOrderDetailsByList @Id, @ProductIdList, @numList, @PriceList
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
COMMIT TRANSACTION
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
RETURN 0
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
--存储过程二
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
CREATE PROCEDURE InsertOrderDetailsByList
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@Id INT,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@ProductIDList NVARCHAR(4000) = NULL,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@NumList NVARCHAR(4000) = NULL,
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
@PriceList NVARCHAR(4000) = NULL
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
AS
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
SET NOCOUNT ON
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
DECLARE @Length INT
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
DECLARE @FirstProductIdWord NVARCHAR(4000)
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
DECLARE @FirstNumWord NVARCHAR(4000)
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
DECLARE @FirstPriceWord NVARCHAR(4000)
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
DECLARE @ProductId INT
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
DECLARE @Num INT
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
DECLARE @Price MONEY
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
SELECT @Length = DATALENGTH(@ProductIDList)
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
WHILE @Length 0
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
BEGIN
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
EXECUTE @Length = PopFirstWord @@ProductIDList OUTPUT, @FirstProductIdWord OUTPUT
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
EXECUTE PopFirstWord @NumList OUTPUT, @FirstNumWord OUTPUT
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/sqlserver/)
&n