Question

I have MS Access 2007 database with the following schema:

Main table Object< # Object_PK, ... >

Child table Electric_Consumption< $ Object_PK, # Electric_Consumption_PK, ... >

Child table Water_Consumption< $ Object_PK, # Water_Consumption_PK, ... >

Child table Educational_Object< $ Object_PK, # Educational_Object_PK, ... > which has child tables defined like this:

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

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

Here is the picture that should make things clearer:

enter image description here

I use ADO and C++ to insert data.

First I need to enter data for main table Object. I can successfully do that with INSERT query.

My problem is following:

After the above operation I need to insert Object's primary key into child tables, since it is their foreign key.

Allow me to describe exactly what I need so community can help me:

As I said, first I insert data into main table Object.

Then I need to insert data and Object's primary key into child tables.

Browsing through Internet I have found @@IDENTITY that might help me but I do not know if it works for my case.

To make things harder, this will be done in for loop ( the value of the Object_PK is the same in every INSERT and is equal to the value of the last inserted record for the Object ) , something like this:

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

Then the same thing should be repeated for tables Water_Consumption and Educational_Object.

After I finish this, I need to add data in the Educational_Object's child tables.

The same as above, only instead of Object_PK I need to add Educational_Object_PK.

Here is the pseudo-code to clarify things better:

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 ??

Can you please tell me which SQL statement to use for this, and demonstrate how to use it by providing a small pseudo code?

I understand that my description of the problem might be confusing so if you need further clarification leave a comment and I will edit my post.

Thank you.

Best regards.

Was it helpful?

Solution

Yes, you want to use SELECT @@IDENTITY as a multiuser-safe way to retrieve the most recently-created AutoNumber (sometimes called "IDENTITY") value. The things to remember are:

  • You execute a SELECT @@IDENTITY query immediately after you perform the INSERT on the parent table.
  • You store the returned value in a Long Integer variable.
  • You use the variable to populate the Foreign Key values in the child table(s).

The following is VBA code, but you can treat it as pseudo-code:

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

OTHER TIPS

If the Object_PK is predictable, such as you are using an Autonumber field, you could first determine the next key by something like: SELECT Max([Object_ID]+1) AS NewKey FROM ObjectTable; then use that for all of the other tables (or simply retrieve the MAX key value after storing the Object); How is the primary key defined?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top