Microsoft Access - Append information using selection criteria from another query

Asked By Amberly Chirolla
15-Mar-11 05:05 PM
This seems like it should be so simple, but I can't figure it out.

I am trying to append Contact information from one table to an archive table.  The Contact table fields: Contact ID (autonumber primary key) Employee ID, Participant ID, Date, and Comments.

I want to append to the archive table (and then delete from current table) all rows in the Contact table for Participants in a particular Program.

I created qselParticipants which uses the Program ID to select the Participants (Participant ID).  I am trying to use the Participants returned in that query and the Contact table to select all of the rows in the contact table which are related to the Participant in that Program.

With no join, I get each Contact row repeated for each participant (even though only one participant is related to each contact); with a join, I get nothing.

Once I get this figured out, I'll use a copy of it as a delete query.

What am I doing wrong?
  James Murray replied to Amberly Chirolla
15-Mar-11 05:45 PM
Hello Amberly,

If you could please provide your table definitions, table names and a little sample data so we can assist writing the insert query for you.

"With no join, I get each Contact row repeated for each participant (even though only one participant is related to each contact); with a join, I get nothing."

Are you sure it is a one to one relationship? You could be joining two tables on incorrect ID's which would give you a one to many relationship with incorrect data.

About deleting data...

Lets say you can have insert command and then you have a delete command that deletes what you just inserted?

What if the insert fails?

I'd recommend going a subquery when doing your delete command.

DELETE from CONTACT_TBL where CONTACT_ID in (SELECT CONTACT_ID from CONTACT_ARCHIVE_TBL)

This doesn't just look at the current transaction but all contacts that have been backed up in the archive. However, if the insert fails, it will fail to delete the data from the contact_tbl as it doesn't exist just yet in the CONTACT_ARCHIVE_TBL table).

Lets say for some freakish reason it doesn't delete from the contact_tbl because the records were in use by someone else after it successfully archived.

On another time/another archive it cleans up the CONTACT_TBL by deleting all items that are archived.

  Amberly Chirolla replied to James Murray
17-Mar-11 12:13 PM
Thanks for your help! Hopefully I've put enough definition and data below.  If not, let me know what more I need to provide... (I'm really a novice but have somehow managed to create a pretty complex database that we've used for about four years now.) 

There are about 12 different tables that contain information that I'm archiving.  I'm not having a problem with the ones that are connected through ProgramID (at least haven't so far).  I think that's because the criteria is based on direct input, instead of query results.

The current and archive tables are the same.  The archive data are in another database--just copied the structure--because that's what my director wanted.  I know there is some argument as to whether archived data should be kept in the same database or a different one, but this is the route I'm going.  (If it's easier, I could change it, I guess.)

Original data is in:  S:\Database\Zoran 4.0_be.mdb
Archive data is in: S:\Database\Zoran 4.0_archive_be.mdb

For example, this one works fine:

INSERT INTO tblPrograms IN 'S:\Database\Zoran 4.0_Archive_be.mdb'
SELECT tblPrograms.*
FROM tblPrograms INNER JOIN qARCsel1Program ON tblPrograms.ProgramID = qARCsel1Program.ProgramID;

where qARCsel1Program is:

SELECT tblPrograms.ProgramID, tblPrograms.program, tblPrograms.Description
FROM tblPrograms
WHERE (((tblPrograms.ProgramID)=[Enter Program ID:]));

On to the problem ...

tblContacts:
ContactID (long integer, auto number, primary key)
EmployeeID (long integer, is the primary key for tblEmployee)
ParticipantID (long integer, is the primary key for tblParticipants)
Date (date/time)
Comments (text)

Relationships:
tblParticipants-tblContacts one to many
tblEmployees-tblContacts one to many

I know my query names are odd--its just for the archive ones.

qARCsel2Participants:

        SELECT tblParticipants.ProgramID, tblParticipants.ParticipantID

        FROM tblParticipants

        WHERE (((tblParticipants.ProgramID)=[Enter Program ID:]))

        ORDER BY tblParticipants.ParticipantID;



Sample data:

tblContacts
ContactID EmployeeID ParticipantID Date Comments
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date.
9 2 107 1/5/2007 Can't make final payment until next week.
10 2 108 1/5/2007 Will make final payment after loan check comes through which will be in about 2 weeks.
11 2 98 1/5/2007 Is mailing full payment today.
12 2 86 1/12/2007 Email to me stating that she is trying to drum up funds and wants to have until the end of January.
13 2 88 1/30/2007 Called and emailed her about her final payment
14 2 91 2/5/2007 Talked with daughter, Kathryn, as well as emergency contact, Angela. Will be processing refund and sending it to her daughter, Kathryn Brown, 898 Oak St. Unit #1310, Atlanta, GA 30310

APPEND QUERY
qARC3appContacts:
INSERT INTO tblContacts IN 'S:\Database\Zoran 4.0_Archive_be.mdb'
SELECT tblContacts.*
FROM tblContacts, qARCsel2Participants;

When I run it like this, I get nothing. 

So I changed it to a select query just to see what would happen

SELECT tblContacts.*, qARCsel2Participants.ParticipantID
FROM tblContacts, qARCsel2Participants;

and get this:

qARC3appContacts
ContactID EmployeeID tblContacts.ParticipantID Date Comments Participant ID
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 175
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 177
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 178
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 179
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 180
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 181
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 182
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 183
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 184
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 185
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 186
8 2 132 12/18/2006 per email she would like us to use the credit card on file for each payment on each payment due date. 79
9 2 107 1/5/2007 Can't make final payment until next week. 175
9 2 107 1/5/2007 Can't make final payment until next week. 177
9 2 107 1/5/2007 Can't make final payment until next week. 178
9 2 107 1/5/2007 Can't make final payment until next week. 179
9 2 107 1/5/2007 Can't make final payment until next week. 180
9 2 107 1/5/2007 Can't make final payment until next week. 181
9 2 107 1/5/2007 Can't make final payment until next week. 182
9 2 107 1/5/2007 Can't make final payment until next week. 183
9 2 107 1/5/2007 Can't make final payment until next week. 184
9 2 107 1/5/2007 Can't make final payment until next week. 185
9 2 107 1/5/2007 Can't make final payment until next week. 186
9 2 107 1/5/2007 Can't make final payment until next week. 79
10 2 108 1/5/2007 Will make final payment after loan check comes through which will be in about 2 weeks. 175
10 2 108 1/5/2007 Will make final payment after loan check comes through which will be in about 2 weeks. 177
10 2 108 1/5/2007 Will make final payment after loan check comes through which will be in about 2 weeks. 178
10 2 108 1/5/2007 Will make final payment after loan check comes through which will be in about 2 weeks. 179


When I run this:

SELECT tblContacts.*, qARCsel2Participants.ParticipantID
FROM qARCsel2Participants INNER JOIN tblContacts ON qARCsel2Participants.ParticipantID = tblContacts.ParticipantID;

I get nothing.

Re: Deleting.  That makes sense.  I'm not so concerned about someone being in the records because these are old ones and I generally make everyone close out when I'm updating/maintaining, etc. so the risk is low.  But something could happen.  Can I do it when the data is in a separate database as currently set up? 

So how would the whole thing look? (append and delete queries with the subquery)

Thanks again. 
  James Murray replied to Amberly Chirolla
17-Mar-11 01:08 PM
Hello Amberly,

Good documentation!

SELECT tblContacts.*, qARCsel2Participants.ParticipantID
FROM tblContacts, qARCsel2Participants;

Whenever you add a table but you don't join it, for every entry in table A you'll get a combination of A plus B and vice versa. If you offered a power tool (powertool_tbl), saw (saw_tbl) and hammer (hammer_tbl) as a prize to your customers for winning a drawing and your query was

Select powertoolname, sawname, hammername
from powertool_tbl, saw_tbl, hammer_tbl

And you get 80,000 results

Then you tell your customers ,"YOU COULD WIN ONE OF 80,000 PRIZES!"

and really the query its just listing every possible combination of the 10 power tools, 16 saws and 12 hammers.

Now,

My knee jerk reaction why your query WITH the join wouldn't be working...


Is this (highlighted red) column in qARC3appContacts really named tblContacts.ParticipantID?

If so, your query should be.

SELECT tblContacts.*, qARCsel2Participants.ParticipantID
FROM qARCsel2Participants INNER JOIN tblContacts ON qARCsel2Participants.tblContacts.ParticipantID = tblContacts.ParticipantID;

The above query may not be a valid query.

I'd strongly recommend renaming this column to simply ParticipantID if it is indeed named this way.

If you want to keep its foreign key table name, use the underscore _ symbol to break it from the table and column name.

Such as: tblContacts_ParticipantID

A period in true sql is used for tunnelling from a large object to a child object (server, database, table, column).

Thats why it doesn't seem logical to include it in your query (why you excluded it).

Lets say you rename it and your query should then be:

SELECT tblContacts.*, qARCsel2Participants.ParticipantID
FROM qARCsel2Participants INNER JOIN tblContacts ON qARCsel2Participants.tblContacts_ParticipantID = tblContacts.ParticipantID;

If you STILL get 0 results, make sure the participantID in both tables are the same data type (int preferably).

About the delete:

INSERT INTO tblPrograms IN 'S:\Database\Zoran 4.0_Archive_be.mdb'
SELECT tblPrograms.*
FROM tblPrograms INNER JOIN qARCsel1Program ON tblPrograms.ProgramID = qARCsel1Program.ProgramID;

Your delete command should be:

DELETE FROM tblPrograms
WHERE tblPrograms.ProgramID in (Select ProgramID from tblprograms IN 'S:\Database\Zoran 4.0_Archive_be.mdb')

What you are doing is a sub query.

While we read querys left to right, top to bottom.

Databases actually perform subqueries first and work their way back so essentially its first going out and reading all the programID's in the archive.

Then it says ,"ok we have a list of programID's that are archived and now they shouldn't exist in the production database, lets start deleting"

I hope this helps,
James
  Amberly Chirolla replied to James Murray
17-Mar-11 04:34 PM
Thank you so much!

The first issue is solved.  Now, on to the delete.

When I try to delete based on whether or not the information is already in the archive (using the code you gave me), I get this error:  "... can't delete 1 record due to key violations and 0 records due to lock violations." (I have over 150 programs in the main database and 3 so far in the archive database, so I'm not sure why there's only 1 record that it can't delete--there should be 3, right?.)

 

When I do this,

DELETE tblPrograms.*

FROM tblPrograms INNER JOIN qARCsel1Program ON tblPrograms.ProgramID = qARCsel1Program.ProgramID;


I get “Could not delete from specified table.”

 

When I do a simple delete query with the program number as my criteria, it deletes it for me.


I thought that maybe it was a permissions thing on the server, but since the last one worked, I don't think that's it.

Also, one other question ... I'm not sure when this happened (I guess when I was splitting it--for a few years, it was not split), but my back end is .mdb and my front end is .accdb.  Can this present a problem?

Thanks again for your help.

Amberly
  James Murray replied to Amberly Chirolla
17-Mar-11 06:48 PM
Hello Amberly,

Usually when you go to run a delete and it bombs out it cancels the entire transaction (in sql). So if there is 1 row in tblprograms that another table is dependant on, it should stop the entire delete. The delete may simply be erroring on the first delete attempt and its not working and saying 1 row is giving you an error.

A "Key" violation may mean a relationship key. Meaning that tblprograms.ID has a relationship and exists in another table. If tblprograms.ID exists in tblprogramscustomer as programsID then you cannot delete the entry from tblprograms until the record is deleted from tblprogramscustomer first. This removes the dependancy. Think of it this way, you can't kill the king till the knights are dead, can't kill the knights till the pawns are dead. You work your way up to the king to kill the final record.

You may have to run two insert and two deletes if you are archiving more than one table so that you don't lose data in the archiving/deletion process.

In fact when looking at your insert query again...

INSERT INTO tblPrograms IN 'S:\Database\Zoran 4.0_Archive_be.mdb'
SELECT tblPrograms.*
FROM tblPrograms INNER JOIN qARCsel1Program ON tblPrograms.ProgramID = qARCsel1Program.ProgramID;

Is qARCsel1Program dependant on tblPrograms? or is tblPrograms dependent on qARCsel1Program?

You can see your relationships visually by using Access's Relationships tool.



Here's how to get to it in Access 2003.



Relationships are just like... relationships. Tables are dependant on others. They can even be co-dependant.

Here is an example of a database I wrote (see image below).

Customers is a big table of all the customers.

Customers have multiple locations and these are stored in the Cust_Loc table. (one to many)

Customers have services performed at their locations in cust_svs_loc table. (one to many to one)

There are different types of services (Services) table. (one to one)

Now, I simply CAN'T delete a customer (DELETE FROM CUSTOMERS) unless I delete ALL the items in the Cust_Svs_Loc table AND the locations in the Cust_Loc table because these tables have a direct dependancy on the Customers table. A customer location cannot still exist in the database if the customer does not exist. If it were to happen this creates "Orphaned" data in the database and when someone is scrolling through all Customer Locations they'll find tons of locations where the customer name doesn't show but just the ID. I like to call this "Bad times" in databasing.

I also can't delete any thing from the Services that exist in the Cust_Svs_Loc table as Cust_Svs_Loc has a dependancy on services.

Also, Access is really funny about deletions and insertions.

There are certain settings in access that can allow a deletion of an item if it only affects 1 record regardless of the relationship and on "MASS DELETIONS" (2 rows or above) it will prompt the user that they can't do that. So deleting 1 record in access means ,"Heres your freebie, but don't try it again in large quantity".

People generally just don't delete these rows in relational databases and rather use flags to show that the item is no longer used or has been archived. Then they setup their forms to look for all programs where "Archived" column is null or "no".

So if I no longer wanted a service to be used in the service's table, I'd add a column called "Disabled" and set my form that creates items in Cust_Svs_Loc to only show services where disabled = "No". The service still exists, users just can't see it any longer. If they pull up old records, they can see the service but they can no longer add new tickets with that service type.



Unfortunately, I put the pretty arrows on the relationship map and access just shows the lines.

The real question comes down to...

Do you have any dependent relationships on the programs table that would prevent it from doing mass deletions against this table?

If there are, you may find pertinent data being lost during the archiving process if tblprograms is the only records being archived and there is a one to one or one to many table based off tblprograms that should be archived as well.

Keep in mind in the relationships view that just because there is a line between the table "tblprograms" and another it does not always mean there is a dependancy on tblprograms but rather tblprograms is dependant on another, if tblprograms is dependant on another it can be deleted without causing any issues.

You can see which one is dependent on the other by right clicking the line and choose "Edit Relationship"



Let me know how it goes.

Sincerely,
James
  Amberly Chirolla replied to James Murray
21-Mar-11 12:58 PM
Thanks again for all your help.  These are things that were sort of fuzzy in the back of my mind, but the way you explain it makes so much sense.  Everything I know has sort of been cobbled together.

So, as I was going through I found one relationship (because of the funky query results) that is incorrect.  (I had it as one to many and it should have been one to one.)  The back end is located on a server and for some unknown reason it's locked and I can't change any of the tables and relationships.  So now I'm just waiting for our tech guy to try to unlock it from his end.

My next question is ... I know that at one point I erased a relationship because it was not allowing us to adjust insurance information for our participants.  But I realized that there are several tables that should have relationships that don't.  For example, there should be a there should be a one-to-many relationship between tblParticipants and tblFees.  But there is nothing there.  (I probably deleted it on accident at one point.)  Should I go back in and add it?  I did not have a problem when I was archiving that section.  I'm a little afraid that I might cause cascading problems and don't want to touch it.  (Of course this one, I do need to fix because it interferes with the archive process.)

Again, thank you so much for your help.  Not just on these particular problems, but the information in general is really interesting to me and I feel like more of the puzzle pieces fit together.

Amberly
  Amberly Chirolla replied to James Murray
21-Mar-11 03:50 PM
It worked!  Yay.  Thanks for all your tips.  I've only done one program so far, but the others should come out alright.  I'm not working again until next Monday, but hopefully things will go smoothly at that point too.

Thanks again for all your help.

Amberly
Create New Account
help
O, [CS%G \ PX> "1> (X_4 / P"W> / I.FR(Z / I]HR.DJ, IA4AEE; = *#QR'898?Q' MDYJO / X:T&ZOY;^XT339KR5"DEQ):HTCJ4V$%B, D%?EQZ< = * , / 2-0_LOP9J% MRIQ-_ BBB@`HHHH`* ** * "BBB@`HHHH M`* ** * "BBB@`KS_XJ? \ `(.T[_KJW \ J] KS_XJ? \ `(.T[_KJW \ J:W$ST:[_X_ M)_ \ `KHW \ ZAJ:[_X_)_ \ `KHW \ ZAI %%%%`PHHHH * ** * "BBB@ JK?ZE8:7 L BBB@`HHHH * * M* * "BBB@`KS_`.*G_(.T[_KJW \ J]`KS_`.*G_(.T[_KJW \ J:W$ST:[_X_)_^ MNC?SJ&IKO_C \ G_ZZ-_.H:0!1110, * ** *`"BBB@`HHHH`* ** *`"BBB@`HHHH` M BBB@`HHHH * ** * "BBB@`KS_`.*G_(.T[_KJ MW \ J]`KS_`.*G_(.T[_KJW \ J:W$ST:[_X_)_^NC?SJ&IKO_C \ G_ZZ-_.H:0!1 M110, * ** *`"BBB@`HHHH`* ** *`"BBB@`HHHH C(.*H?V = XA_P"A@@_ \ %X_^+H_L[Q#_`-#! M!_X+Q_ \ `%T )K5AJ$OAK[.DKW = [# / #-&ZPIND, <RNNY2Z*3A1NPR@ \ D`<+6+ M#X> O = 8$TVH6B173SF:6 / 4[.*> UE9D1 R0I
time we get them the addresses are not in any standard format, i.e, Street, St, St., RR 1, Rt. 1, Rt 1, etc. I am creating a macro that will examine ends with characters that need to be changed. Here is an example, 501 East Station St as entered should convert to 501 E. Station St. East to E. & Street to St. The problem is when checking for St and replaceing with St. will also change Station to St.ation Selection.Replace What: = " St", Replacement: = " St.", LookAt: = xlPart, _ SearchOrder: = xlByRows, MatchCase: = True, SearchFormat
into separate columns, that is city, state, zip. Here is what my problem looks like. OAK PARK, IL 60302 OAK PARK, IL 603020000 OAK PARK, IL 60302 OAK PARK, IL 60302 OAK PARK, IL 603024272 OAK PARK, IL 60302 OAK PARK, IL 603022609 OAK PARK, IL 603024272 OAK PARK, IL 60304 OAK PARK, IL 603020000 OAK PARK, IL 60302
now a minimum of 4 levels deep. Say I have an assembly / kit part number; ST-987589 That kit contains 3 part numbers; ST-658 ST-586 ST-369 Of those 3 part numbers, 2 of them are sub assemblies that contain further numbers; ST-658 contains ST-256 ST-125 ST-524 and ST-369 contains; ST-201 ST-145 ST-723 So my report would