?
快捷搜索:  as  test  1111  test aNd 8=8  test++aNd+8=8  as++aNd+8=8  as aNd 8=8

銀河999官網 電玩:小議主子表INT自增主鍵插入記錄的方法

?

主子表最常見的大年夜概便是用在進銷存、MRP、ERP里面,比如一張販賣訂單,訂單Order(ID,OrderDate),訂單明細OrderDetail(OrderID, ProductID, Num,Price)這個大年夜概便是最簡單的主子表了,兩個表經由過程ID與OrderID建立關聯,這里主鍵ID是自增的INT類型,OrderID是表OrderDetail的外鍵。當然,鍵的選擇措施很多,現在我們選擇的是在sql里面最簡單的措施。

對付這樣的表布局,我們最常見的問題便是保存的時刻如何處置懲罰鍵值的問題,由于兩個表關聯異常的慎密,我們進行保存的時刻必要把它們放在一個事務里面,這時問題就會呈現,Order表中的ID是自動增長型的字段?,F在必要我們錄入一張訂單,包括在Order表中插入一銀河999官網 電玩筆記錄以及在OrderDetail表中插入多少筆記錄。由于Order表中的ID是自動增長型的字段,那么我們在記錄正式插入到數據庫之前無法事先得知它的取值,只有在更新后才能知道數據庫為它分配的是什么值,然后再用這個ID作為OrderDetail表的OrderID的值,著末更新OderDetail表。然則,為了確保數據的同等性,Order與OrderDetail在更新時必須在事務保護下同時進行,即確保兩表同時更行成功,這個就會有點困擾。

辦理這類問題常見的主要有兩類措施:

一種是微軟在網上書店里應用的措施,應用了四個存儲歷程。改裝一下,使之相符現在的例子

--存儲歷程一

CREATE PROCEDURE InsertOrder

@IdINT = NULL OUTPUT,

@OrderDateDATETIME = NULL,

@ProductIDListNVARCHAR(4000) = NULL,

@NumListNVARCHAR(4000) = NULL,

@PriceListNVARCHAR(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銀河999官網 電玩

COMMIT TRANSACTION

RETURN 0

--存儲歷程二

CREATE PROCEDURE InsertOrderDetailsByList

@IdINT,

@ProductIDListNVARCHAR(4000) = NULL,

@NumListNVARCHAR(4000) = NULL,

@PriceListNVARCHAR(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

@SourceStringNVARCHAR(4000) = NULL OUTPUT,

@FirstWordNVARCHAR(4000) = NULL OUTPUT

AS

SET NOCO銀河999官網 電玩UNT ON

DECLARE @OldwordNVARCHAR(4000)

DECLARE @LengthINT

DECLARE @CommaLocationINT

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

@OrderIdINT = NULL,

@ProductIdINT = NULL,

@PriceMONEY = NULL,

@NumINT = NULL

AS

SET NOCOUNT ON

INSERT OrderDetail(OrderId,ProductId,Price,Num)

SELECT @OrderId,@ProductId,@Price,@Num

RETURN 0

插入時,傳入的子表數據都是長度為4000的NVARCHAR類型,各個字段應用“,”瓜分,然后調用PopFirstWord分拆后分手調用InsertOrd銀河999官網 電玩erDetail進行保存,由于在InsertOrder中進行了事務處置懲罰,數據的安然性也對照有保障,幾個存儲歷程設計的精美新奇,很故意思,然則子表的幾個數據大年夜小不能跨越4000字符,生怕不大年夜保險。

第二種措施是我對照常用的,為了方便,就不用存儲歷程了,這個例子用的是VB.NET。

‘處置懲罰數據的類

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號

ID = myDBTools.SqlData.ExecuteScalar(trans, CommandType.Text, _IDENTITY_SQL)

'從記錄

If Not arParam Is Nothing Then

For Each sql In arParam

'將剛得到的ID號代入

sql = sql.WordStr(_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,是對常見的數據庫操作封裝后的類,這個類對數據庫進行直接的操作,有履歷的.NET數據庫法度榜樣員基礎上都邑有,一些聞名的例子法度榜樣一樣平常也都供給。

上面的是通用部分,下面是對詳細單據的操作

Publid class Order

Public _OrderDate as date‘主表記錄

Public ChildDt as datatable‘子表記錄,布局與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 Chi銀河999官網 電玩lddt 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

上面的兩個例子為了方便解釋,去掉落了一些查驗驗證歷程,有興趣的同伙可以參照網上書店的例子鉆研第一種措施,或者根據自己的必要對第二種措施進行改動。

免責聲明:以上內容源自網絡,版權歸原作者所有,如有侵犯您的原創版權請告知,我們將盡快刪除相關內容。

您可能還會對下面的文章感興趣:

快三平台开户