zoukankan      html  css  js  c++  java
  • 小议主子表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

  • 相关阅读:
    高效读写的队列:ConcurrentLinkedQueue
    线程池的堆栈问题
    内部类(嵌套类)
    线程池的内部实现
    线程池
    线程阻塞工具类:LockSupport
    CountDownLatch(倒计时器)、CyclicBarrier(循环栅栏)
    ReentrantReadWriteLock(读写锁)
    ReentrantLock(重入锁)的好搭档:Condition 条件
    ReentrantLock
  • 原文地址:https://www.cnblogs.com/zkwarrior/p/4855133.html
Copyright © 2011-2022 走看看