国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

小議主子表INT自增主鍵插入記錄的方法

2024-07-21 02:10:38
字體:
供稿:網(wǎng)友
   主子表最常見的大概就是用在進(jìn)銷存、mrp、erp里面,比如一張銷售訂單,訂單order(id,orderdate),訂單明細(xì)orderdetail(orderid, productid, num,price)這個(gè)大概就是最簡單的主子表了,兩個(gè)表通過id與orderid建立關(guān)聯(lián),這里主鍵id是自增的int類型,orderid是表orderdetail的外鍵。當(dāng)然,鍵的選擇方法很多,現(xiàn)在我們選擇的是在sql里面最簡單的方法。

    對于這樣的表結(jié)構(gòu),我們最常見的問題就是保存的時(shí)候怎樣處理鍵值的問題,因?yàn)閮蓚€(gè)表關(guān)聯(lián)非常的緊密,我們進(jìn)行保存的時(shí)候需要把它們放在一個(gè)事務(wù)里面,這時(shí)問題就會(huì)出現(xiàn),order表中的id是自動(dòng)增長型的字段。現(xiàn)在需要我們錄入一張訂單,包括在order表中插入一條記錄以及在orderdetail表中插入若干條記錄。因?yàn)閛rder表中的id是自動(dòng)增長型的字段,那么我們在記錄正式插入到數(shù)據(jù)庫之前無法事先得知它的取值,只有在更新后才能知道數(shù)據(jù)庫為它分配的是什么值,然后再用這個(gè)id作為orderdetail表的orderid的值,最后更新oderdetail表。但是,為了確保數(shù)據(jù)的一致性,order與orderdetail在更新時(shí)必須在事務(wù)保護(hù)下同時(shí)進(jìn)行,即確保兩表同時(shí)更行成功,這個(gè)就會(huì)有點(diǎn)困擾。


解決這類問題常見的主要有兩類方法:


一種是微軟在網(wǎng)上書店里使用的方法,使用了四個(gè)存儲(chǔ)過程。改裝一下,使之符合現(xiàn)在的例子


--存儲(chǔ)過程一


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

 

--存儲(chǔ)過程二

 

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

 

--存儲(chǔ)過程三

 

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

 

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

 

--存儲(chǔ)過程四

 

create procedure insertorderdetail

    @orderid    int = null,

    @productid     int = null,

    @price  money = null,

 

    @num   int = null

as

    set nocount on

    insert orderdetail(orderid,productid,price,num)

    select @orderid,@productid,@price,@num

   return 0

插入時(shí),傳入的子表數(shù)據(jù)都是長度為4000的nvarchar類型,各個(gè)字段使用“,”分割,然后調(diào)用popfirstword分拆后分別調(diào)用insertorderdetail進(jìn)行保存,因?yàn)樵趇nsertorder中進(jìn)行了事務(wù)處理,數(shù)據(jù)的安全性也比較有保障,幾個(gè)存儲(chǔ)過程設(shè)計(jì)的精巧別致,很有意思,但是子表的幾個(gè)數(shù)據(jù)大小不能超過4000字符,恐怕不大保險(xiǎn)。

第二種方法是我比較常用的,為了方便,就不用存儲(chǔ)過程了,這個(gè)例子用的是vb.net。

‘處理數(shù)據(jù)的類

 

public class dbtools

 

    private const _identity_sql as string = "select @@identity as id"

 

    private const _id_for_replace as string = "_id_for_replace"

 

   ‘對主子表插入記錄

 

   public function insfathersonrec(byval main_sql as string, byval paramarray arparam() as string) as integer

 

        dim conn as new sqlconnection(strconn)

 

       dim id as integer

 

        conn.open()

 

        dim trans as sqltransaction = conn.begintransaction

 

        try

 

            '主記錄

 

            mydbtools.sqldata.executenonquery(trans, commandtype.text, main_sql)

 

            '返回新增id號(hào)

 

            id = mydbtools.sqldata.executescalar(trans, commandtype.text, _identity_sql)

 

            '從記錄

 

            if not arparam is nothing then

 

                for each sql in arparam

 

                    '將剛獲得的id號(hào)代入

 

                    sql = sql.replace(_id_for_replace, id)

 

                    mydbtools.sqldata.executenonquery(trans, commandtype.text, sql)

 

                next

 

            end if

 

            trans.commit()

 

            catch e as exception

 

                  trans.rollback()

 

            finally

 

            conn.close()

 

        end try

 

        return id

 

    end function

 

end class

 

上面這段代碼里有mydbtools,是對常見的數(shù)據(jù)庫操作封裝后的類,這個(gè)類對數(shù)據(jù)庫進(jìn)行直接的操作,有經(jīng)驗(yàn)的.net數(shù)據(jù)庫程序員基本上都會(huì)有,一些著名的例子程序一般也都提供。

 

上面的是通用部分,下面是對具體單據(jù)的操作

 

publid class order

 

    public _orderdate as date            ‘主表記錄

 

    public childdt as datatable           ‘子表記錄,結(jié)構(gòu)與orderdetail一致

 

    public function save() as integer

 

         dim str as string

 

         dim i as integer

 

         dim arparam() as string

 

         dim str as string=”insert into order(orderdate) values(‘” & _orderdate & “’)”

 

        if not childdt is nothing then

             arparam = new string(childdt.rows.count - 1) {}

             for i=0 to childdt.rows.count-1

                 arparam(i)= ”insert into orderdetail(orderid,productid,num,price) values(_id_for_replace,” & drow(“productid) & “,” & drow(“num”) & “,” drow(“price”) & “)”

 

          next i

        end if

        return (new dbtools). insfathersonrec(str,arparam)

end class


上面的兩個(gè)例子為了方便解釋,去掉了一些檢驗(yàn)驗(yàn)證過程,有興趣的朋友可以參照網(wǎng)上書店的例子研究第一種方法,或者根據(jù)自己

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 奉新县| 通化县| 仙游县| 枞阳县| 永修县| 扶绥县| 石柱| 万山特区| 丘北县| 徐州市| 桦甸市| 白河县| 吕梁市| 威信县| 丽江市| 铁力市| 遂宁市| 承德县| 老河口市| 安国市| 洪江市| 汶川县| 怀安县| 永平县| 喀什市| 大连市| 运城市| 东城区| 花莲市| 康马县| 榆中县| 宝山区| 泽普县| 阜宁县| 博乐市| 太康县| 吉首市| 兴国县| 平南县| 西乌| 革吉县|