小议主子表INT自增主键插入记录的方法SQL server]教程

http://www.chinesejy.com/jishu/508/519/2006061781665.html

主子表最常见的大概就是用在进销存、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

 

    @Id                INT = NULL OUTPUT,

 

    @OrderDate        DATETIME = NULL,

 

    @ProductIDList     NVARCHAR(4000) = NULL,

 

    @NumList          NVARCHAR(4000) = NULL,

 

    @PriceList          NVARCHAR(4000) = NULL

 

AS

 

    SET NOCOUNT ON

 

    SET XACT_ABORT ON

 

    BEGIN TRANSACTION

 

   --插入主表

 

    INSERT Orders(OrderDate) select @OrderDate

 

     SELECT @Id = @@IDENTITY

 

      -- 插入子表

 

     IF @ProductIDList IS NOT NULL

 

            EXECUTE InsertOrderDetailsByList @Id, @ProductIdList, @numList, @PriceList

 

    COMMIT TRANSACTION

 

    RETURN 0

 

--存储过程二

 

CREATE PROCEDURE InsertOrderDetailsByList

 

    @Id        INT,

 

    @ProductIDList     NVARCHAR(4000) = NULL,

 

    @NumList      NVARCHAR(4000) = NULL,

 

    @PriceList      NVARCHAR(4000) = NULL

 

AS

 

    SET NOCOUNT ON

 

    DECLARE @Length INT

 

    DECLARE @FirstProductIdWord NVARCHAR(4000)

 

    DECLARE @FirstNumWord NVARCHAR(4000)

 

    DECLARE @FirstPriceWord NVARCHAR(4000)

 

    DECLARE @ProductId INT

 

    DECLARE @Num INT

 

    DECLARE @Price MONEY

 

    SELECT @Length = DATALENGTH(@ProductIDList)

 

    WHILE @Length > 0

 

    BEGIN

 

        EXECUTE @Length = PopFirstWord @@ProductIDList OUTPUT, @FirstProductIdWord OUTPUT

 

        EXECUTE PopFirstWord @NumList OUTPUT, @FirstNumWord OUTPUT

 

        EXECUTE PopFirstWord @PriceList OUTPUT, @FirstPriceWord OUTPUT

 

        IF @Length > 0

 

        BEGIN

 

            SELECT @ProductId = CONVERT(INT, @FirstProductIdWord)

 

            SELECT @Num = CONVERT(INT, @FirstNumWord)

 

            SELECT @Price = CONVERT(MONEY, @FirstPriceWord)

 

            EXECUTE InsertOrderDetail @Id, @ProductId, @Price, @Num

 

        END

 

    END

 

--存储过程三

 

CREATE PROCEDURE PopFirstWord

 

    @SourceString   NVARCHAR(4000) = NULL OUTPUT,

 

    @FirstWord      NVARCHAR(4000) = NULL OUTPUT

 

AS

 

    SET NOCOUNT ON

 

    DECLARE @Oldword        NVARCHAR(4000)

 

    DECLARE @Length         INT

 

    DECLARE @CommaLocation  INT

 

    SELECT @Oldword = @SourceString

 

    IF NOT @Oldword IS NULL

 

    BEGIN

 

        SELECT @CommaLocation = CHARINDEX(',',@Oldword)

 

        SELECT @Length = DATALENGTH(@Oldword)

 

        IF @CommaLocation = 0

 

        BEGIN

 

            SELECT @FirstWord = @Oldword

 

            SELECT @SourceString = NULL

 

            RETURN @Length

 

        END

 

        SELECT @FirstWord = SUBSTRING(@Oldword, 1, @CommaLocation -1)

 

        SELECT @SourceString = SUBSTRING(@Oldword, @CommaLocation + 1, @Length - @CommaLocation)

 

        RETURN @Length - @CommaLocation

 

    END

 

    RETURN 0

 

------------------------------------------------

 

--存储过程四

 

CREATE PROCEDURE InsertOrderDetail

    @OrderId    INT = NULL,

    @ProductId     INT = NULL,

    @Price  MONEY = NULL,

 

 &n

posted @ 2015-10-04 22:45  _海阔天空  阅读(877)  评论(0编辑  收藏  举报