Violating a simple foreign key contraints in MS-SQL generates following useless error-message:
Error: The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_employee". The conflict occurred in database "AgentAndAgency", table "dbo.employee", column 'id'.
SQLState: 23000
ErrorCode: 547
Missing is the detail, which key is causing the foreign key contraint, so, e.g. PostgreSQL would say in the same situation:
Error: inserting into table employement violates foreign key contraint- „FK_employee“
Details: key (employee_id)=(958980) does not exist in table „employee“.
MS-SQL does not provide this information, which makes it completely useseless (I'm bulk-inserting thoundsands of records).
Question: how can I make MS-SQL tell me at least one missing key?
Because the data may contain multiple errors, the "identify one error, fix that and iterate" technique tends not to work out well.
No server, so far as I'm aware, will identify all missing keys - they terminate the work as soon as they've identified that an error has occurred1 since the presence of just a single error may mean that the entire task needs to be aborted, rather than the data needing fixing.
To identify all of the errors, a better approach is to perform your bulk-insert into a staging table that doesn't have any constraints. Then write a query that left joins to the employee table and identifies all missing keys.
1Rather than potentially wasting resources by attempting to identify the complete set. But from a "relational-purist" perspective, that's what they ought to do - since we try to keep everything set-based, the errors ought to be sets too.
Instead of the update, do a SELECT from your update data WHERE employee_id NOT IN (SELECT employee_id FROM employee)
Should give you the list of missing employee_ids
Related
I am trying to remove all data from a table and re-add it, but I get the below exception:
An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code Additional information: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
At first I though it was pretty obvious, until I looked at my database (below). To check if I was missing something I deleted all relevant rows in SSMS successfully. If I can delete the rows without foreign key constraints in SQL, why cant I do it in EF?
EDIT:
I am trying to delete from the rooms table
Based on the error message and that you are attempting to delete from the Rooms table, it seems likely that you have an enforced foreign key constraint on the Images table tied to RoomID.
You can determine what relationship is causing the issue by right-clicking the Rooms table in SSMS and clicking "Show Dependencies". This will show you all of the schema-bound dependencies which will be based on foreign keys.
Assuming that is the case, deleting those rows from Rooms would orphan the records in Images or potentially tie them to the records you are inserting (if doing an identity insert), not certain what your intention is. You have two options if you wish to proceed:
Delete the records constrained by the foreign key.
Disable the enforcement of the foreign key in SSMS by right-clicking the foreign key, click Modify, and set "Enforce Foreign Key Contraint" to "No". You may also need to set the Insert and Update specifications to No Action.
Ideally you are just deleting some records and removing the constraint is not necessary, since that compromises the referential integrity of your database.
I'm trying to insert initial data into a DB2 database in DbUnit using DatabaseOperation.INSERT.execute(...) which works fine with some datasets. In order to insert some datasets however, I need to disable foreign key constraints first (because the tables in some datasets can be listed in a 'wrong' order).
I'm disabling the foreign key constraints with command SET INTEGRITY FOR <table_name> OFF, but when I try to insert the data after calling that command, I get this error:
com.ibm.db2.jcc.am.SqlException: DB2 SQL Error: SQLCODE=-668, SQLSTATE=57016, SQLERRMC=1;SCHEMA.TABLE, DRIVER=4.17.30
The IBM error code explanation isn't much helpfull here. Is there something I need to do after setting integrity on a table and before inserting data into that table?
EDIT:
I found this in the documentation for the OFF statement: "Specifies that the tables are placed in set integrity pending state. Only very limited activity is allowed on a table that is in set integrity pending state."
If I understand it correctly, this means that when I turn off the integrity checks on a table, I cannot perform any write/modify operations on it! What's the point of turning the integrity check off then? I need to find a way to do this.
You are not "disabling the foreign key constraints with command SET INTEGRITY". SET INTEGRITY OFF basically means "I'm not sure about the integrity of this table data, so I'd rather restrict access to it until I figure out what's wrong".
To temporary disable foreign key verification you might try ALTER TABLE foo ALTER FOREIGN KEY bar NOT ENFORCED.
First, I want to talk a little about the Foreign key constraint rule and how helpful it is. Suppose I have two tables, a primary table with the primary column called ID, the other table is the foreign one which also has a primary column called ID. This column in the foreign table refers to the ID column in the primary table. If we don't establish any Foreign key relation/constraint between those tables, we may fall foul of many problems related to integrity.
If we create the foreign key relation for them, any changes to the ID column in primary table will 'auto' reflect to the ID column in the foreign table, changes here can be made by DELETE, UPDATE queries. Moreover, any changes to the ID in the foreign table should be constrained by the ID column in the primary table, for example there shouldn't any new value inserted or updated in the ID column of the foreign table unless it does exist in the ID column of the primary table.
I know that SQLite doesn't support foreign key constraint (with full functions as detailed above) and I have to use TRIGGER to work around this problem. I have used TRIGGER to work around successfully in one way (Any changes to the ID column in the primary table will refect to the ID column in the foreign table) but the reverse way (should throw/raise any error if there is a confict occurs, for example, there are only values 1,2,3 in the ID column of the primary table, but the value 2 in the ID column of the foreign table is updated to 4 -> not exist in the primary table -> should throw error) is not easy. The difficult is SQLite doesn't also support IF statement and RAISERROR function. If these features were supported, I could work around easily.
I wonder how you can use SQLite if it doesn't support some important features? Even working around by using TRIGGER is not easy and I think it's impossible, except that you don't care about the reverse way. (In fact, the reverse way is not really necessary if you set up your SQL queries carefully, but who can make sure? Raising error is a mechanism reminding us to fix and correct and making it work exactly without corrupting data and the bugs can't be invisible.
If you still don't know what I want, I would like to have some last words, my purpose is to achieve the full functionality of the Foreign key constraint which is not supported in SQLite (even you can create such a relationship but it's fake, not real as you can benefit from it in SQL Server, SQL Server Ce, MS Access or MySQL).
Your help would be highly appreciated.
PS: I really like SQLite because it is file-based, easy to deploy, supports large file size (an advantage over SQL Server Ce) but some missing features have made me re-think many times, I'm afraid if going for it, my application may be unreliable and corrupt unpredictably.
To answer the question that you have skillfully hidden in your rant:
SQLite allows the RAISE function inside triggers; because of the lack of control flow statements, this must be used with a SELECT:
CREATE TRIGGER check_that_id_exists_in_parent
BEFORE UPDATE OF id ON child_table
FOR EACH ROW
BEGIN
SELECT RAISE(ABORT, 'parent ID does not exist')
WHERE NOT EXISTS (SELECT 1
FROM parent_table
WHERE id = NEW.id);
END;
I'm attempiting to use cx_OracleTool's CopyData.py script to copy data between two tables on separate Oracle schemas/instances:
http://cx-oracletools.sourceforge.net/cx_OracleTools.html
When I run it against my tables, I get the error:
No primary or unique constraint found on table.
I don't know much about Oracle, to be honest, but from what I can tell the tables don't seem to have any PK constraint or anything like that defined.
The merits of this aside, I think it's simply been setup that way for expediency, and it's unlikely to change anytime nearterm.
Is there any way to get copyData.py to run in this scenario without a PK constraint?
Cheers,
Victor
The issue is that CopyData checks to see if the row exists in the destination table, and it can't do that without a unique key.
If it is acceptable to insert all rows and not update changed ones, use the --no-check-exists option. According to the code this will bypass the primary key check.
Otherwise, use the --key-columns=COLS option to manually specify the columns to be used as the unique key. This will also bypass the primary key check.
To prevent duplicate table entries in a database I use a primary key. I just add the information and if it is a duplicate then the primary will be a duplicate and it will not add to the table.
Should I also do a SQL query (before trying to add to the database) to see if the entry exists? Or is this redundant since I already have the primary key set?
It is redundant to check for presence of a value if you already have a constraint to prevent duplicates.
But it would also be ineffective to check before you insert, because some other concurrent client might insert that value in the moment between your check and your insert. So even if you check first, you'd still need to handle duplicate key errors.
Defining "unique constraint" on table with desired column will fix everything. If there's a dupplicate you will get error.
With most database platforms, when you create the primary key, the operation will fail if there are duplicate entries, so there should be no need to test for this beforehand.
Usually you'd get an exception or an error code from the call to SQL engine. If you need to handle that or not depends on your application logic. For example if it is a new username, and it already exists in the database, then exception is part of you application logic, and you will provide new user with a message about why registration failed.