UPDATE failed due to key violation VBA SQL Access - sql

I need help with this
I have an MS Access db form which will enable users edit details about a project and the new values entered will be saved to the db table when the save button is clicked I am using the sql UPDATE syntax to do this and my code is similar to below
Private Sub Save_Click()
ltemp = " UPDATE Table1 "
ltemp = ltemp & " SET ClientName = 'ANN' "
ltemp = ltemp & " WHERE ProjectID = 2333 "
CurrentDb.Execute (ltemp)
End Sub
with this code, nothing happened. The code would execute with no errors but the value on the table wouldnt change.
I tried the code
DoCmd.RunSQL " UPDATE Table1 SET ClientName = 'ANN' WHERE ProjectID = 2333"
with this i got a long error message which indicated that the records couldnt be updated due to key violation. The problem is that the field 'ClientName' is not the primary key, although it is linked (in a relationship) to the primary key of another table.
both codes work to update other fields except this one which is in a relationship with the primary key of another table.

Obviously there is no record in your 'client' table with the 'ANN' id, so it cannot be set as a valid value for the corresponding\foreign key field in your updated table.
currentDb.execute instruction will not return any error message (not like the 'DoCommand' one) because it's not supposed to, as long as the syntax is correct (see below). You could try to use the currentDb.RecordsAffected to check if any record was changed by your instruction. Check parameters available for the execute method for further details.
Access Help:
"In a Microsoft Jet workspace, if you provide a syntactically correct SQL statement and have the appropriate permissions, the Execute method won't fail — even if not a single row can be modified or deleted. Therefore, always use the dbFailOnError option when using the Execute method to run an update or delete query. This option generates a run-time error and rolls back all successful changes if any of the records affected are locked and can't be updated or deleted."

You are attempting to violate the referential integrity set up on your database.
As you've noted, there is another table, which will look something like this:
CREATE TABLE Client
(
ClientName VARCHAR(100),
... other client fields here
);
And there is a FOREIGN KEY setup between columns Table1.ClientName and Client.ClientName.
To avoid this, either:
INSERT a client with the name ANN into the other table
DROP the foreign key constraint on Table1.ClientName if you intend to violate the constraint (but note that joins may fail when the client is missing)
Change the design and start using surrogate keys, such as ClientID and referencing the Surrogate key in your other tables (instead of 'natural' keys like Client Name). This way, clients can get married, change their names etc and your database won't break :)

Related

Failed to enable constraints MySQL using MySqlClient.DataHandler

Error message
The above image shows the error image whenever I tried to execute the sql command to get data table in VB .NET as shown below: (note: sqlstr and dttable has been declared before function headers, therefore no declaration here)
Public Function retrieveProducts() As DataTable
sqlstr = "SELECT * FROM products;"
dttable = MysqlClient.DataHandler.GetDataTable(sqlstr, conn, True)
If Not IsNothing(dttable) Then
Return dttable
End If
Return Nothing
End Function
Before you guys link the problem to any "duplicate" question, I want to inform that I had browsed a ton of answers from similar questions and none of them worked for me.
Here are the solutions I tried:
Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints
I tried ? dttable.GetErrors(0).RowError on debug mode and it says "Referenced object has a value of 'Nothing'."
I also tried removing constraints of data table in my program (putting the remove function before the MysqlClient.DataHandler.GetDataTable function causes nothing to be returned)
Note:
The solution for dataset.enforceConstraints = false should be my last resort since my supervisor requested the program structure to revolve around MySqlClient data handler. If it's possible I wanted to resolve this without using data set.
As for the table itself, it has a foreign key constraint referencing to another table, the values in the table didnt violate any non-null and unique constraints. Besides that, other table with foreign key constraint too however, can be retrieved successfully. So I am confused with what is wrong.
DDL of the target table

Validation rule in sql and access

I am trying to create a validation rule but using SQL in Access. I am very new to this. I know how to do it in regular Access design view, but don't know how to do it when using the create table command. So far I have,
CREATE TABLE CUSTOMERS
(
CustomerName TEXT (20),
Gender TEXT (10),
FavoriteFood TEXT (20)
);
Would like to add a validation rule to gender for just male/female/notknown.
A field's Validation Rule is a DAO.TableDef property which can't be created using Access SQL.
If you want to use Access SQL for something similar, use a CHECK CONSTRAINT. This statement will limit Gender values to male, female, or unknown.
CREATE TABLE CUSTOMERS
(
CustomerName TEXT (20),
Gender TEXT (10) NOT NULL,
FavoriteFood TEXT (20),
CONSTRAINT allowed_genders CHECK
(
Gender IN ('male','female','unknown')
)
);
Note a CHECK CONSTRAINT can only be used in Access SQL when executed from ADO. I executed that statement with CurrentProject.Connection.Execute, which is an ADO method.
Some consequences of this approach may make it unacceptable to you ...
The constraint is not visible in table Design View.
When the constraint is violated, the error message does not appear until you attempt to save the record.
And the error message is based on the constraint name ... which is not very user-friendly in this case.
Because of the constraint, you can not delete the table from the Access UI; you would have to first execute DROP CONSTRAINT allowed_genders and then delete the table, or execute DROP TABLE CUSTOMERS which will discard both the table and constraint at the same time.
You might prefer to create a simpler version of the table and then set the Validation Rule with DAO.
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Set db = CurrentDb
Set tdf = db.TableDefs("CUSTOMERS")
tdf.Fields("Gender").ValidationRule = "IN ('male','female','unknown')"
tdf.Fields("Gender").ValidationText = "Gender must be male, female, or unknown"
Notes:
The DAO methods allow you to also include a user-friendly Validation Text message.
When the Validation Rule is violated, Access will display the error message as soon as you attempt to move to the next field.
Finally yet another approach would be to create a lookup table which contains your allowed Gender values, make CUSTOMERS.Gender a foreign key to that lookup field, and enforce referential integrity.
Any of those 3 approaches might fit your situation; choose whichever seems to fit best. :-)

Syntax Error in From Clause deleting MSystem table records, relationship issue

I am looking to delete a relationship that was created with code in an Access 2007 DB, using vb.net. The DB may have been upgraded from an older level.
So here is what has been done, I open the DB with ADO connection string, the db is encrypted and password protect, I also open in Mode =12, to get exclusive rights. This all works. I grant SELECT, DELETE, and ALTER permissions on MSysObjects, and MSysRelationships to admin user.
The issue is the relationship used is a GUID, it is stored in these System tables as only text, but it can not be deleted from the tables for which the relationship was made, ie.
ALTER TABLE [MyTable] DROP CONSTRAINT '{D86827C0-some-GUID-6A6449F1FB07}';
or
ALTER TABLE [MyTable2] DROP CONSTRAINT '{D86827C0-some-GUID-6A6449F1FB07}';
This fails becuase the GUID can not be found on the table, I have tried the tables on both sides of the relationship. I am able to get the szRelationship value, which is how I have it to apply to the above ALTER query, yet as stated, it is not found as a relationship name on either table. This led me to believe that the DB may have been migrated from older Access. The System Object tables show this relationship, so I know it exists and it appears in the Relationships diagram. It can also be deleted there manually. I have hundreds of DBs that needs this edit though.
So my alternate approach was to delete directly from the two system tables.
DELETE [MSysObjects], [MSysRelationships] FROM [MSysObjects]
INNER JOIN [MSysRelationships]
WHERE [MSysObjects].[Name] = [MSysRelationships].[szRelationship]
AND [MSysObjects].[Name] = '" & relationName & "';
But this returns a Syntax error on the From Clause. I have searched high and low for alternative statements to try and to debug this one, with not luck...This link provided some samples and a starting point for syntax.
delete from two tables in one query
As it turns out the syntax error on my alter statement needed these [ ]....
ALTER TABLE [MyTable] DROP CONSTRAINT [{D86827C0-some-GUID-6A6449F1FB07}];
Works now.

How to validate data in sql server?

I have an issue related to data in sql server. In my database some of the constraint were not enabled i.e. they were not checked , After some time working on it we found this issue that a parent rows can be deleted without deleting child, which was an issue. I enabled all the constraint in the database using query
ALTER TABLE tbl_name CHECK CONSTRAINT ALL
above query was executed on all the tables of that database without any error . But my concern is whether it will work or not , if it will work on the existing data then what will happen to that data whose parent table data has been deleted.
I want to know is there any way such that I can validate such data data whose parent record doesn't exist in the entire database. There are about 270 constraint containing FOREIGN KEY AND UNIQUE KEY . I don't want to go for manual option.
Please help me out.
ALTER TABLE tbl_name CHECK CONSTRAINT ALL
only re-enables the constraints. Importantly, the constraints are not checked against the existing data in the database (nor are they trusted by the optimizer). If you want that to occur, you need to specify WITH CHECK as well:
ALTER TABLE tbl_name WITH CHECK CHECK CONSTRAINT ALL
(And yes, the word CHECK appears twice)
If you execute this, and there are orphaned child rows (or other invalid constraints), then the ALTER TABLE will fail with an error message. There's nothing SQL Server can do to fix this issue - it's for you to decide whether to a) remove the orphaned rows, or b) to re-create, in some manner, a suitable parent row for them.
You can also add the 'ON DELETE CASCADE' code to the end of foreign keys to prevent orphaned child rows from persisting.
This is more of a 'better practice' going forward than a solution, but I believe Damien_The_Unbeliever has answered your main question.

Access Database - Auto INSERT\UPDATE - Qt4

In a registration software made with Qt4, I open an Access .mdb database, update it with the user-provided fields.
It has currently a table clients with six fields:
CustomerNumber, FullName, CNICNumber, ResidentialAddress, ResidentialPhoneNumber, MobileNumber
where CustomerNumber is primary key and a number, while all others are text. There are a few records present. But when another record with same CustomerNumberis tried to be inserted, there is an error:
QODBCResult::exec: Unable to execute
statement: "[Microsoft][ODBC Microsoft
Access Driver] The changes you
requested to the table were not
successful because they would create
duplicate values in the index, primary
key, or relationship. Change the data
in the field or fields that contain
duplicate data, remove the index, or
redefine the index to permit duplicate
entries and try again."
"[Microsoft][ODBC Microsoft Access
Driver] The changes you requested to
the table were not successful because
they would create duplicate values in
the index, primary key, or
relationship. Change the data in the
field or fields that contain duplicate
data, remove the index, or redefine
the index to permit duplicate entries
and try again." "QODBC3: Unable to
execute statement"
I then found the UPDATE query, but the following code gives another error:
query.exec("UPDATE clients"
"SET FullName='"+cname+"', CNICNumber='"+cnic+"', ResidentialAddress='"+caddress+"', ResidentialPhoneNumber='"+cphone+"', MobileNumber='"+cmobile+"'"
"WHERE CustomerNumber="+cnumber+";");
The variables cname, cninc, caddresss, cphone, cmobile, cnumber are strings with values. But the error with the above code is:
QODBCResult::exec: Unable to execute
statement: "[Microsoft][ODBC Driver
Manager] Function sequence error"
"[Microsoft][ODBC Driver Manager]
Function sequence error" "QODBC3:
Unable to execute statement"
What is the solution to this, i.e. how to insert a new record when the primary key is not present but update existing record with same primary key?
You are missing spaces. The actual command you are executing is equivalent to
query.exec("UPDATE clientsSET Fullname...
there is no such table as clientsSET.
Here is what you intended
query.exec("UPDATE clients"
" SET FullName='"+cname+"', CNICNumber='"+cnic+"', ResidentialAddress='"+caddress+"', ResidentialPhoneNumber='"+cphone+"', MobileNumber='"+cmobile+"'"
" WHERE CustomerNumber="+cnumber+";");
If these are user-input values you are vulnerable to SQL injection. You need to be careful to scrub all the string values (eg. replace all ' with '').
What is the solution to this, i.e. how
to insert a new record when the
primary key is not present but update
existing record with same primary key?
This is known informally as an UPSERT. See this answer that relates to Access.
query.exec("UPDATE clients"
...CNICNumber='"+cnic+"', ...
My guess would be that CNICNumber shouldn't have single quotes around it.
...CNICNumber="+cnic+", ...
But it's impossible to tell for sure without knowing your table structure.
Can you try with:
+ " SET FullName='"+cname+ ...
+ " WHERE CustomerNumber="+cnumber+";");
in the second and third row?