append query failed key violation - sql

My append query fails due to key violation but only one new records, the old records append normally just the new ones that I added fail.
DoCmd.RunSQL "INSERT INTO [Order_Item] ([Order_ID],[Item_ID],[Quantity]) Values (" & orderNumber & ", [Enter Item ID], [Enter Quantity])"
Order_ID and Item_ID are foreign keys

Access will raise an error re. key violation when you insert something into the FK via sql that isn't in the related table. You may also get a similar error for primary key violations.
Here is some code (which you'd need to adapt to your model) to check the keys exists in the related tables and that the 'mapping' does not already exist in the mapping table before you insert.
Select Case True
Case IsNull(DLookup("[ID]", "Table1", "[ID]=" & num1))
MsgBox ("ID does not exist in Table1")
Case IsNull(DLookup("[ID]", "Table2", "[ID]=" & num2))
MsgBox ("ID does not exist in Table2")
Case Not (IsNull(DLookup("[ID1]", "Map", "[ID1]=" & num1 & "And [ID2]=" & num2)))
MsgBox ("Mapping already exists")
Case Else
DoCmd.RunSQL "INSERT INTO [Map] VALUES (" & num1 & ", " & num2 & ")"
End Select

I just resolved a similar issue that was caused by a key violation issue. Two lessons that I learned might be helpful to others with similar issues:
make sure that your relationships diagram shows every table - I didn't (and the non-visible table was linked to a visible one, and that was the problem link). It's too easy to forget the links you've set up!
if you're not sure which field in the query is driving the key violation error, type a valid value into a blank field on the table - if it's the field causing the problem it'll tell you which field needs a related entry.
Of course be extra vigilant if this is a "live" system and remove any "test" data!

Related

Autonumber - start from ZERO

So, I know how to add an autonumber field to a table using SQL:
dblocal.Data.Execute "CREATE TABLE " & TableName & " (" & FieldName & " COUNTER(1,1) )"
Where dblocal is the passed database reference with TableName & FieldName the appropriate names for the desired creation of the table.
However, I want the counter to start at ZERO not ONE. And I know it's possible because the table I need to repair / duplicate starts with ZERO
What am I not finding on the internet to aid me in this task?
My search-fu fails me.

ms-access SQL linked sheet row order retention

Is there a way to guarantee row order in a table derived from a linked sheet? I seem to occasionally lose row order (which unfortunately has meaning) when I select from a Linked Sheet while looping over a number of sheets & WB.
DoCmd.TransferSpreadsheet acLink, , "linked_sheet ", sfile, False, "some_sheet!A1:U100"
CurrentDb().Execute "select '" & identifier & "' as id1, " & identifier2 & " as id2, i.* into temp_table from linked_sheet i"
CurrentDb().Execute "alter temp_table add column ky counter primary key"
The keys are correctly ordinal, but the rows are not the same as the original spreadsheet.
The problem is intermittent and does not occur on the same Sheet/WB every time.
If I catch the error, then go back and rerun the same code, it will return correct original row order as it appears in the sheet.
The rows are not missing, they are moved to a different location in temp_table.
I'm holding the WB in memory while querying the linked_sheet could this be causing the problem?
To wax philosophically, you should not care about the order of rows inserted into the target table. That is at the db engine's discretion. The only time you should be concerned is upon presentation, when you select from the temp table. This is the most likely reason that "order by" is not supported by this syntax.
May I inquire why it is an issue?
Other databases use a syntax "insert into x from (select * from y order by z)", where the "order by" controls the order in which the rows are presented to the insert statement. But it still remains that the order of data in the db should not be relevant.

MS access code to insert data into another table (validation rule error)

I have a user form that inserts data into "user" table and "organizer" table when I click a button, user data gets inserted with no problem, but it prompts me to enter the value (organization_name) again in a small dialogue box -which supposed to take from the text field and insert into organizer table- ,
then gives me an error saying "ms access set one row null due to validation rule violation"
NOTE: I didn't put any validation rule for the "organization_name" anywhere
Private Sub InsertSqlIntoOrgTable()
Dim orgName As String, SqlOrgNameInsert As String
orgName = txtOrgName.Value 'takes the value from text field
SqlOrgNameInsert = "INSERT INTO ORGANIZER (ORG_NAME) VALUES (" & orgName & ") "
DoCmd.RunSQL SqlOrgNameInsert
End Sub
SqlOrgNameInsert = "INSERT INTO ORGANIZER (ORG_NAME) VALUES ('" & orgName & "') "
if the field name in table ORGANIZER is really ORG_NAME. Show us your complete table definition in case that this doesn't solve your problem. Because in your last question you posted:
sqlOrgInsertUsrId = "INSERT INTO ORGANIZER (USER_ID) VALUES (" & orgUserId & ")"
Both inserts run into the same table but try to create new independent rows. If USER_ID is primary key then your insert into ORG_NAME can't work that way.
You should learn more about SQL.

How do I update a table with a form in access using VBA or a Macro?

I am doing my best to build my first database, but I have come up against a problem I just cannot find an answer to. I am a complete newbie in this forum and writing any sort of code so please be gentle.
I am trying to create a new record in a table when a student's name is double clicked inside a list box which is inside a form.
List box where I want to take first (StudentID) column value from = lstStudent
Combo box where I want to take the second (CourseID) column value from: cboCourseID
Text box where I want to take third (NoteID) column value from = txtCourseNoteID
The new record is being created in the desired table and there are no incorrect code errors but there are no values being carried across to the fields. The autonumber is being created (AttendanceID) but the other columns are blank. Here is my code:
Private Sub lstStudent_DblClick(Cancel As Integer)
CurrentDb.Execute "INSERT INTO tblAttendance (StudentID, CourseID, NoteID) VALUES ('me.lstStudent','me.cboCourseID','me.txtCourseNoteID')"
End Sub
The fields are populated, so this isn't the issue. The formatting is correct for the target fields and I can't think of anything else in my way.
The new record is being created in the desired table and there are no
incorrect code errors but there are no values being carried across to
the fields. The autonumber is being created (AttendanceID) but the
other columns are blank.
With this INSERT statement, you're supplying text values for those 3 fields in the new row ...
INSERT INTO tblAttendance (StudentID, CourseID, NoteID)
VALUES ('me.lstStudent','me.cboCourseID','me.txtCourseNoteID')
However StudentID, CourseID, and NoteID are numeric fields, so will not accept those text values. In that situation, there is nothing the db engine can insert. You still get a new row added (with the new autonumber value in AttendanceID), but those other fields are empty.
If you include the dbFailOnError option with .Execute, Access will notify you about the problem (error #3464, "Data type mismatch in criteria expression") and abort the insert --- a new row will not be added ...
CurrentDb.Execute "INSERT INTO tblAttendance (StudentID, CourseID, NoteID) VALUES ('me.lstStudent','me.cboCourseID','me.txtCourseNoteID')", dbFailOnError
Use an approach similar to what #HarveyFrench suggested, but eliminate the single quotes from the VALUES list ...
Dim strInsert As String
strInsert = "INSERT INTO tblAttendance (StudentID, CourseID, NoteID)" & vbCrLf & _
"VALUES (" & Me.lstStudent.Value & "," & Me.cboCourseID.Value & "," & _
Me.txtCourseNoteID.Value & ");"
Debug.Print strInsert ' <- view this in Immediate window; Ctl+g will take you there
CurrentDb.Execute strInsert, dbFailOnError
Based on what you've told us, I suspect that will work, but I'm not sure it's the best way to reach your goal. You could open a DAO.Recordset and add the new row there. Or if you can use a bound form, Access would automatically take care of storing a new row ... without the need to write code.
Change this
CurrentDb.Execute "INSERT INTO tblAttendance (StudentID, CourseID, NoteID) VALUES ('me.lstStudent','me.cboCourseID','me.txtCourseNoteID')"
to be this
CurrentDb.Execute "INSERT INTO tblAttendance (StudentID, CourseID, NoteID) _
VALUES ('" & me.lstStudent & "','" & me.cboCourseID & "','" & me.txtCourseNoteID "');"
See also here for useful info

Append data to linked table without knowing Primary Key of main table

I have a Staff Recruitment Database. When all formalities are complete I click a button and basic data is appended to the (recruited) Staff Database .
I also have data for the shift the recruit will work: Hours, Rate of pay etc. This goes into a Linked table.
To append this data I need to know the Primary Key of the recruit. How can I append the data automatically without looking at the table where the basic data is to find the PK?
I'm using INSERT INTO. Staff Database contains the main Staff table and the linked Shifts table.
If the "main" table has an AutoNumber field as its Primary Key then immediately after performing the INSERT INTO statement you can use some code like this to retrieve the PK value you just inserted:
Dim rst AS DAO.Recordset, newPK as Long
Set rst = CurrentDb.OpenRecordset("SELECT ##IDENTITY", dbOpenSnapshot)
newPK = rst(0).Value
rst.Close
Set rst = Nothing
You can then use the newPK value as a foreign key in the related tables.
Edit re: using the new value
Based on the code sample in your comment, try this instead:
strSQL = _
"INSERT INTO tblShifts (StartDt, [To], Hours, StaffLookup) " & _
"IN ""C:\__tmp\Staff.accdb"" " & _
"SELECT qryAdd.DateStarted, qryAdd.To, qryAdd.Hours, " & newPK & " AS StaffLookup FROM qryAdd"
If [tblShifts] really is a linked table then you shouldn't need to use the IN (mydatabase) clause because a linked table will behave just like a local table in this case. Note the corrections to the syntax as well, especially the bracketing of [To] which is a reserved word in Access.
Think I have got a solution. I can retrieve the PK into the recruitment db like this:
DoCmd.RunSQL "INSERT INTO tblCBSStaffLookup ( StaffLookupCBS, NINO ) " & _
"SELECT tblStaff.ID, tblStaff.NINO " & _
"FROM tblStaff IN 'C:\Users\Peter.Home-PC\Documents\NEMS\Databases\Frontends\Staff.accdb' " & _
"WHERE (((tblStaff.NINO)=[Forms]![frmSuccess]![NINO])) "
tblCBSStaffLookup is a table I have now made in the recruitment db to collect the PK and NINO.
WHERE matches the newly arrived NINO to a form in the recruitment db which already has the NINO. I have set up constraints to make sure that NINO's are valid. I have also set up a query in the recruitment db to retrive all NINO's from the main db, so that new recruits don't get added the the main db twice.