2014-02-07 99 views
1

MS Access 2007數據庫使用下面的模式:插入主表的主鍵到子表中多次

主表Object< # Object_PK, ... >

子表Electric_Consumption< $ Object_PK, # Electric_Consumption_PK, ... >

子表Water_Consumption< $ Object_PK, # Water_Consumption_PK, ... >

子表Educational_Object< $ Object_PK, # Educational_Object_PK, ... >其子表格定義如下:

School< $ Educational_Object_PK, # School_PK, ... >

University< $ Educational_Object_PK, # University_PK, ... >

這裏是畫面,應該讓事情更清晰:

enter image description here

我用ADOC++插入數據。

首先,我需要輸入主表Object的數據。我可以通過INSERT查詢成功完成此操作。

我的問題是以下幾點:

上述操作後,我需要插入Object主鍵到子表,因爲這是他們的外鍵。

讓我來形容正是我需要的,以便社會可以幫助我:

正如我所說的,我首先將數據插入到主表Object

然後我需要將數據Object的主鍵插入到子表中。

瀏覽互聯網我發現@@IDENTITY可能會幫助我,但我不知道它是否適用於我的情況。

爲了使事情變得更難,這將在for loop辦妥(Object_PK的價值是每個INSERT相同,等於值最後插入Object),像這樣:

for (//...) 
    L"INSERT INTO Electric_Consumption (Object_PK, field1, field2 ...) 
     values (Object_pk // should I use here @@IDENTITY ?); 

然後同樣的事情應該被重複的表Water_ConsumptionEducational_Object

完成後,我需要在Educational_Object的子表中添加數據。

與上面相同,只能代替Object_PK我需要添加Educational_Object_PK

這裏是僞代碼,以澄清事情做得更好:

L"INSERT INTO Object (...) values (...); //this is OK 

for (...) 
    L" INSERT INTO Electric_Consumption (Object_PK, ...) 
     values (Object_PK, ...)"; // should I use @@IDENTITY here 
            // to get Object_PK ?? 
for (...) 
    L" INSERT INTO Water_Consumption (Object_PK, ...) 
     values (Object_PK, ...)"; // should I use @@IDENTITY here 
            // to get Object_PK ?? 
for (...) 
    L" INSERT INTO Educational_Object (Object_PK, ...) 
     values (Object_PK, ...)"; // should I use @@IDENTITY here 
            // to get Object_PK ?? 
for (...) 
    L" INSERT INTO School (Educational_Object_PK, ...) 
     values (Educational_Object_PK, ...)";// should I use @@IDENTITY here 
            // to get Educational_Object_PK ?? 
for (...) 
    L" INSERT INTO University (Educational_Object_PK, ...) 
     values (Educational_Object_PK, ...)";// should I use @@IDENTITY here 
            // to get Educational_Object_PK ?? 

能否請你告訴我使用這裏面SQL statement,並演示瞭如何通過提供小僞代碼使用它?

我明白我對問題的描述可能會令人困惑,因此如果您需要進一步澄清請留下評論,我將編輯我的帖子。

謝謝。

此致敬禮。

回答

1

是的,您希望使用SELECT @@IDENTITY作爲多用戶安全的方式來檢索最近創建的AutoNumber(有時稱爲「IDENTITY」)值。要記住的事情是:

  • 在父表上執行INSERT後立即執行SELECT @@IDENTITY查詢。
  • 將返回值存儲在Long Integer變量中。
  • 您可以使用該變量來填充子表中的外鍵值。

下面是VBA代碼,但你可以把它當作僞代碼:

Dim lngObject_PK As Long, lngEducational_Object_PK As Long 

Set cmd = New ADODB.Command 
cmd.ActiveConnection = con 
cmd.CommandText = "INSERT INTO [Object] ([Description]) VALUES (?)" 
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255, "my new Object") 
cmd.Execute 
Set cmd = Nothing 

Set rst = New ADODB.Recordset 
rst.Open "SELECT @@IDENTITY", con, adOpenStatic, adLockOptimistic 
lngObject_PK = rst(0).Value 
rst.Close 
Set rst = Nothing 
Debug.Print "Object_PK of newly-created Object record: " & lngObject_PK 

Set cmd = New ADODB.Command 
cmd.ActiveConnection = con 
cmd.CommandText = "INSERT INTO [Electric_Consumption] ([Object_PK],[Description]) VALUES (?,?)" 
cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput, , lngObject_PK) 
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255, "my new Electric_Consumption") 
cmd.Execute 
Set cmd = Nothing 

Set cmd = New ADODB.Command 
cmd.ActiveConnection = con 
cmd.CommandText = "INSERT INTO [Educational_Object] ([Object_PK],[Description]) VALUES (?,?)" 
cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput, , lngObject_PK) 
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255, "my new Educational_Object") 
cmd.Execute 
Set cmd = Nothing 

Set rst = New ADODB.Recordset 
rst.Open "SELECT @@IDENTITY", con, adOpenStatic, adLockOptimistic 
lngEducational_Object_PK = rst(0).Value 
rst.Close 
Set rst = Nothing 
Debug.Print "Educational_Object_PK of newly-created Educational_Object record: " & lngEducational_Object_PK 

Set cmd = New ADODB.Command 
cmd.ActiveConnection = con 
cmd.CommandText = "INSERT INTO [School] ([Educational_Object_PK],[Description]) VALUES (?,?)" 
cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput, , lngEducational_Object_PK) 
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255, "my new School") 
cmd.Execute 
Set cmd = Nothing 
+0

謝謝你的幫助!只有一個問題:也許更好的選擇是使用'SCOPE_IDENTITY()'或'IDENTITY_CURRENT()'?他們在'MS Access'中可用嗎?最好的祝福。 – AlwaysLearningNewStuff

+0

@AlwaysLearningNewStuff就我所知,SELECT @@ IDENTITY是唯一可用於Access數據庫的選項。你提到的另外兩個是T-SQL(Microsoft SQL Server)。 –

+0

還有一個問題:爲了維護[ACID](http://en.wikipedia.org/wiki/ACID)模型,我應該使用'transactions'嗎?如果是這種情況,你可以用小代碼示例來修改答案,以說明這一點?我已將'ADO'調用放在'try/catch'塊中。我已經提出了你的答案。感謝您的幫助。最好的祝福。 – AlwaysLearningNewStuff

0

如果Object_PK是可預測的,如使用的是一個自動編號字段,則可以首先通過像確定的下一個鍵: SELECT MAX([OBJECT_ID] +1)AS則newkey FROM ObjectTable; 然後將其用於所有其他表(或者只是在存儲對象之後檢索MAX鍵值);主鍵是如何定義的?

+1

所有的主鍵是'AUTONUMBER'values。我已經使用'SELECT MAX(Object_PK)...',但這有一個缺陷:現在一切都適用於單用戶,但是如果多個用戶使用我的應用程序,那麼您建議的查詢將執行多次,這可能會導致錯誤的主鍵被退回。這就是我問這個問題的原因。感謝您的幫助。最好的祝福。 – AlwaysLearningNewStuff

+0

在多用戶環境中,您有兩種選擇。您可以使用與您可以調用的以下類似的功能;傳遞它的值以存儲在新的對象記錄中,並接收返回的鍵值。 功能Add_Object(strObjectName作爲字符串),只要 昏暗RS作爲DAO.Recordset 集RS = CurrentDb.OpenRecordset( 「ObjectTable」) rs.AddNew RS!OBJECT_TITLE = strObjectName Add_Object = RS!OBJECT_ID rs.Update rs.Close Set rs = Nothing End Function 將錯誤陷阱添加到上面,您應該沒問題。否則,您可以創建一個TRANSACTION。 –

+0

我不知道Visual Basic,但我會嘗試在Internet的幫助下將您的代碼轉換爲C++。我從未使用過交易,因此需要時間來實施您的解決方案。我們會保持聯繫,請耐心等待。感謝您的幫助。最好的祝福。 – AlwaysLearningNewStuff