Adding foreign key fails unless data is first removed and reinserted after - sql

I have an odd issue with foreign keys. I am trying to perform the following query:
ALTER TABLE [GroupMember] FOREIGN KEY ([Group]) REFERENCES [Group]([GUID])
Which gives me the following error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK__GroupMember__Group__0D25C822". The conflict occurred in database "x", table "dbo.Group", column 'GUID'.
I then verified the existing things, which I have confirmed are all ok:
Referenced table (dbo.Group) has a defined PRIMARY KEY on [GUID] column
Referencing table (dbo.GroupMember) has no [Group]-values which do not exist in [GUID]-column of dbo.Group-table
No similarly referencing foreign keys exist already
From here on, I experimented. Taking some rows in and out, wiping the table, truncating the table. What I can conclude so far:
If I wipe the referencing table using DELETE FROM [GroupMember]; then try to apply the FK constraint, I receive the same error message
If I truncate the referencing table using TRUNCATE TABLE [GroupMember];, I can apply the FK constraint without errors. Additionally, I am able to reinsert the exact same data after applying the FK constraint, without problems.
From this I can conclude that the data itself is not the problem. Can anyone make sense of this? Why am I able to apply the constraint after truncating the table, but not after deleting all records?

If you are using Microsoft SSMS check whether unchecking "Prevent saving changes that require table re-creation" solves the problem. You'll find this in Options > Designers > Table and Database Designers.
I have had similar issues that have been resolved by this. Let me know if it works or not.
Good luck.

Related

Inserting new record and skip if foreign key conflict in sql server 2008 R2

I have the problem similar to this one SQL Server foreign key conflict in a multi values statement? However, in sql server 2008.
While I am reading data from csv file, there is some id already not exist in parent and thus return this error:
INSERT statement conflicted with the FOREIGN KEY constraint
May I know if there is a way similar to MySQL insert ignore. Such that I can simply skip the problematic data.
I accept that if there is no method other than creating a stored procedure with a new temp table (insert into a table without foreign key first, and then re-insert with where foreign_id exists in (select id from parent)).
As I really cannot find any in documentation, asking for ensuring I didn't miss anything.
One general solution which comes to mind would be to temporarily turn off the foreign key constraints, and do the insert. Then, afterwards, you may run a cleanup script/query to remove or rectify child records which are pointing to parents which do not exist. Once your data is in good shape, then turn on the foreign key constraints again.
Read How can foreign key constraints be temporarily disabled using T-SQL? to learn how to disable/enable a foreign key constraint for a single table:
ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint -- disable
ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint -- enable

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.

TRUNCATE TABLE query unable to execute in SSIS because of foreign key

I have a table Person which contains 2 fields.In my another database i have a Participant Table(also have 2 columns).From Participant Table i have to insert values into Person Table.
but before every insertion,i want truncate the person Table.
I have try it out with linking Execute Sql task to Data flow task.But it is showing error that a Primary Foreign key relation exists there.
If I understand correctly, SSIS has nothing to do with your real problem, which is that you want to truncate a table that is referenced by a foreign key constraint. That question has already been answered: Cannot truncate table because it is being referenced by a FOREIGN KEY constraint?
If a table in sql server has foreign key references then you can't truncate. instead in your execute sql task use delete without a where clause.
delete from person_table
If you are really adamant about truncating the table, you could drop the foreign key constraints, then truncate the table then recreate the foreign key constraints. Providing of course, that the user you are running the package as has the privileges to do so.
Create an "Execute SQl" task and run DELETE FROM person
after this task, run your import.
DELETE FROM will give the same result as TRUNCATE TABLE, but if the table has a foreign key pointing to it, it cant be truncated. You have to use the delete command
You won't be able to delete either unless cascading deletes is turned on (or you delete the child records first). Why is this a problem you ask, why can't I do what I want to do? Because if you do then you may lose the integrity of the data. Suppose I have records in table2 which relate to records in table 1. Suppose further that table1 has an autogenerated id. If I could truncate that table, then I leave those records i ntable 2 hanging out without any record to reference them, they have become orphaned. Well but I'm putting the data back in you say. But then they will have new id numbers and you will still lose the relatinoship tothe related data.
Can you drop the FK and truncate and insert and recreate the FK. Yes you can but it is a poor practice and you should not unless you are also recreating those related records.
The best practice is to use a MERGE statement to update or insert depending on what you need.
In SSIS Transfer SQL Server Objects Task Set Property DeleteFirst to TRUE

How to ALTER a table on iSeries that has constraints? Getting "*FILE in use." error

I have a table on a iSeries(IBM-i/AS400) which has some constraints. The table is created with SQL like so, with a handful of foreign keys linking from other tables to this table (actual SQL has been a bit obfuscated here):
CREATE TABLE ABCLIB.ABCDE (
DEIDN INTEGER NOT NULL WITH DEFAULT,
DETTL VARGRAPHIC (50) ALLOCATE(25),
DETYP CHAR (1) NOT NULL WITH DEFAULT);
ALTER TABLE ABCLIB.ABCDE ADD PRIMARY KEY (DEIDN);
ALTER TABLE ABCLIB.ABCFG ADD FOREIGN KEY (FGDEK)
REFERENCES ABCLIB.ABCDE (DEIDN)
ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE ABCLIB.ABCHI ADD FOREIGN KEY (HIDEK)
REFERENCES ABCLIB.ABCDE (DEIDN)
ON DELETE RESTRICT ON UPDATE RESTRICT;
Now, much later, I will need to alter that table to add a field:
ALTER TABLE ABCLIB.ABCDE ADD COLUMN DEICN VARGRAPHIC (100) ALLOCATE(50)
Which results in this message:
Row or object ABCDE in ABCLIB type *FILE in use.
I have checked and there are definitely no object locks on this table at this time. When I check the joblog, I see this:
Constraint cannot be removed from file Q_AT000000.
Constraint(s) not removed from file Q_AT000000.
File ABCDE in ABCLIB not changed.
Row or object ABCDE in ABCLIB type *FILE in use.
Now, I could of course remove and re-add the constraints in question, but I feel like this should not be necessary. The column I am adding has nothing to do with the constraints. I believe this probably is a result of the fact that in fact OS400 (i5/OS) is not really altering the existing table but instead is creating a new table and copying data in, and that is probably where the pain comes in.
But is there a way to possibly suspend the keys and then resume them after the alter?
(Answers that do not involve doing this with SQL or suggest creating the table differently in the first place are not helpful as they are not applicable here...)
The answer is: I missed the fact that there was a lock on one of the tables that had a foreign key pointing to that table. Or, put more bluntly: I am an idiot!
Does Enabling or disabling referential constraints help?

What is the equivalent effect to Truncating a table, when the table is referenced by a foreign-key

Straight out of the MSDN docs for Sql Server 2005:
You cannot use TRUNCATE TABLE on tables that:
Are referenced by a FOREIGN KEY constraint.
Participate in an indexed view.
Are published by using transactional replication or merge replication.
I want the effect of a TRUNCATE (specifically the fact that it resets IDENTITY type columns), but I can't use one in my case because my table is referenced by a foreign-key elsewhere in the database.
Update: This is for a testing configuration where I am clearing out the referencing table as well, so foreign-key integrity is a non-issue.
What other ways are there to get around this?
You can delete all the rows and then do a DBCC CHECKIDENT (Tablename, RESEED, 0) to reset the identity seed
But again DELETE is fully logged while TRUNCATE is minimally logged and will be many times faster
Another option is to drop the foreign key constrains then do a truncate and then recreating the foreign key constraints
The fact that it is refernced by a foreign key is the clue you need to not truncate a table or you would be creating orphaned records. This is why truncate table is not allowed if a foreign key exists.
The correct process is to first delete the refernced records, if any, then drop the FK constraint, then truncate the table then reinstate the fk constraint. If you skip step one, you will create a data integrity nightmare where the record pointing to oldid 100 is not pointing to the new record that happens to get assigned to 100 and it isn;t the record it should match to.
You can drop the foreign key, truncate the table, and then recreate the foreign key.
You will need to drop the constraint, trunc the table, and then add the constraint back. However, you should be very careful with this. If there are rows in the table that you are dropping the FK reference to you will not be able to add it until those rows are deleted or the FK column in the other table is clear.