Primary Key Resetting Issue with foreign keys and delete - sql-server

I have a set of tables which I am going to clear out and upload new data into. One of these, Person has foreign keys pointing to it which prevent me from using TRUNCATE Table even though the other tables are empty.
I have used DELETE FROM after turning off the foreign key checks to get around this. This works except when I insert new values they start at the old value going up and I need them to reset to start at 1 again (or at least some consistent predictable value)
DBCC CHECKIDENT ([Person], RESEED, -1); or DBCC CHECKIDENT ([Person], RESEED, 0); I have seen suggested on other places for resetting the identity but give no useful results for me instead yielding:
Checking identity information: current identity value 'NULL'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
How can I either get truncate to work with the foreign keys pointing to my table OR using delete to clear the table get the primary key's auto increment to reset and start at 1?

You cannot truncate a table, if there are foreign keys pointing to it.
One way would be, to temporarily drop the foreign keys and after truncating recreate them.
Disabling foreign key constraint, still can't truncate table? (SQL Server 2005)

The DBCC command should work. I have removed the square brackets and added single quotes:
DBCC CHECKIDENT ('dbo.Person', RESEED, 0);

Related

Resetting the primary key to 1

I have a script for microsoft sql server database which has hundreds of tables and tables contains data as well. This is the database of a web application.what I want to do is to delete the previous records and reset the primary key to 1 or 0.
I have tried
`DBCC CHECKIDENT ('dbo.tbl',RESEED,0); `
but it does not work for me as in most of the tables the primary key is not identity.
I can not truncate the table as its primary key is being used as FK in many other tables.
I have also tried to add the identity specification in the primary key of the table and run the checkident query and then changing it back to non-identity spec, but after adding the record again it starts from where it left.
Making changes in the code is not an option for me.
please help.
According with your question I am not sure about the main objective, Why? If you need truncate a lot of tables and change their structures to have an Identity property why you can't disabled the FK? . In the past I have used an standard process for rebuild a table and migrate all the information, this represent a group of steps, I would try to help you but you should follow the next steps.
Steps:
1) Disable FK for alter the structure of your tables. You can get the solution for this task in the next link:
Temporarily disable all foreign key constraints
2) Alter the table with the new property Identity, this is a classic process of ALTER TABLE xxxxxx.
3) Execute the syntax that previously posted :
DBCC CHECKIDENT ('dbo.tbl',RESEED,0);
Try to follow this path and if you have any problem only ask us.
You can not truncate table that have relation. You shoud remove relation firstly.
My understanding of this question:
You have a database with tables that you want to empty and next have them use primary key values starting at 0 or 1.
Some of these tables use an identity value and you already have a solution for those (you know you can find out which columns have an identity by using the sys.columns view? Look for the is_identity column).
Some tables do not use an identity but get their pk values from an unknown source, which we can't modify.
The only solution I see, is creating an after insert trigger (or modifying) on those tables that subtracts from the new pk value.
E.g.: your "hidden generator" will generate a next value 5254, but you want the next pk value to become one:
CREATE TRIGGER trg_sometable_ai
ON sometable
AFTER INSERT
AS
BEGIN
UPDATE st
SET st.pk_col = st.pk_col - 5253
FROM sometable AS st
INNER JOIN INSERTED AS i
ON i.pk_col = th.pk_col
END
You'll have to determine the next value and thus the "subtract value" for each table.
If the code also inserts child records into tables with a foreign key to this table, and uses the previously generated value, you have to modify those triggers as well...
This is a "last resort" solution and something I would recommend against in any scenario that has other options. Manipulating primary key values is generally not a good idea.

unable to truncate a parent table even after disabling a FK constraint in sql server

I am unable to truncate from a parent table by only disabling the FK constraint in the referring table . I had to actually drop the constraint in the referring table to be able to truncate the parent table.
I did the above step after first truncating the child table.....so I did follow the right order....do i really need to delete the constraint and then bulk insert the data and then re-create the FK constraint?
If you wanna use TRUNCATE then yes, dropping and recreating the constraint is the only way.
Confirmation in doc (with more explanations)
You cannot use TRUNCATE TABLE on a table referenced by a FOREIGN KEY
constraint; instead, use
DELETE statement without a WHERE clause. Because TRUNCATE TABLE is not
logged, it cannot activate a trigger.
If the child table is empty (or all of the relevant FK values are set to NULL), you should be able to DELETE from the parent table without disabling or dropping the constraint.
However you won't be able to use TRUNCATE even if you disable the constraint and even if the child table is empty. In this case SQL Server checks at the DDL level that the constraint exists and bails out long before it will ever bother checking the data for constraint violations (so it doesn't matter that the table is empty).
So, just use DELETE in your case. Unless you are doing this 50,000 times a day, trying to get this to work with TRUNCATE seems to be a lot of trouble for very little gain.

SQL Server Repeatedly using of deleted identity PK

Just a general question.
I have a table with IDENTITY PK which is not connected with any table through.
There is another and only FK in the table.
I run DELETE command on that table by some condition.
I can INSERT any new records into the table with auto-inserted next PK IDs.
BUT there is no re-using of ID numbers in PK.
If I run something like
DECLARE #max_PKid BIGINT;
SET #max_PKid = (SELECT ISNULL(MAX(PKid), 0) FROM Table WHERE FKid=#somevalue);
DBCC CHECKIDENT ('Table', reseed, #max_PKid)
right after DELETE, there will be access violation problems on next INSERT
Question 1: Is it good practice in general having intervals in unordered (say, unseeded) PKids in the table after doing DELETE/INSERT without using DBCC CHECKIDENT? Should I care on them?
Question 2: If not, what can I do about?
No you should not worry. There are also other circumstances in which you can get a 'hole' in an IDENTITY range. For example, if you start a transaction, insert 100,000 rows into a table, then rollback that transaction - those IDENTITY values are then gone. This is not something you should be concerned about.

Clear all the rows in a table resetting the identity specification back to zero and without affecting the foreign keys?

We have already created the database framework, with all the relations and dependencies. But inside the tables were just the dummy data, and we need to get rid of these dummy data, and start adding the correct ones. How can we clear everything and leave the primary keys (IsIdentity: yes) back to zero, and also without affecting the foreign-table relational structure.
Thanks a lot!
You can take the following steps:
-- disable all foreign key constraints
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
-- delete data in all tables
EXEC sp_MSForEachTable "DELETE FROM ?"
-- enable all constraints
exec sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
More on disabling constraints and triggers here
if some of the tables have identity columns we may want to reseed them
EXEC sp_MSforeachtable "DBCC CHECKIDENT ( '?', RESEED, 0)"
Note that the behaviour of RESEED differs between brand new table, and one which had had some date inserted previously from BOL:
DBCC CHECKIDENT ('table_name', RESEED, newReseedValue)
The current identity value is set to
the newReseedValue. If no rows have
been inserted to the table since it
was created, the first row inserted
after executing DBCC CHECKIDENT will
use newReseedValue as the identity.
Otherwise, the next row inserted will
use newReseedValue + 1. If the value
of newReseedValue is less than the
maximum value in the identity column,
error message 2627 will be generated
on subsequent references to the table.
I'd use TRUNCATE:
-- Truncate table (very fast, and it resets Identity as well)
EXEC sp_MSForEachTable "TRUNCATE TABLE ?"
Of course, disable and re-enable check constraints too, as suggested by kristof.
Reseeding:
DBCC CHECKIDENT (yourtable, reseed, 1)
is for setting the primary key on 1
delete from table should delete the data, but not affect any other things.
Generate Database schema-only sql file using Database publishing wizard and enable the option to drop the tables if exists. Run this script on your database and This will flush everything and give you fresh schema as you need.

Deleting a SQL row ignoring all foreign keys and constraints

I have a row in a table. This row has an ID column referenced in a few other tables with millions of rows. The SQL statement to delete the row always times out. From my design, I know the row I wish to delete is never referenced any where else. Hence I would like SQL to ignore having to check all other tables for a foreign key reference to this row and delete the row immediately. Is there a quick way to do this in SQL 2008?
Perhaps something along the lines of:
DELETE FROM myTable where myTable.ID = 6850 IGNORE CONSTRAINTS
Or something along those lines.
You can set the constraints on that table / column to not check temporarily, then re-enable the constraints. General form would be:
ALTER TABLE TableName NOCHECK CONSTRAINT ConstraintName
Then re-enable all constraints with
ALTER TABLE TableName CHECK CONSTRAINT ConstraintName
I assume that this would be temporary though? You obviously wouldn't want to do this consistently.
Yes, simply run
DELETE FROM myTable where myTable.ID = 6850
AND LET ENGINE VERIFY THE CONSTRAINTS.
If you're trying to be 'clever' and disable constraints, you'll pay a huge price: enabling back the constraints has to verify every row instead of the one you just deleted. There are internal flags SQL keeps to know that a constraint is 'trusted' or not. You're 'optimization' would result in either changing these flags to 'false' (meaning SQL no longer trusts the constraints) or it has to re-verify them from scratch.
See Guidelines for Disabling Indexes and Constraints and Non-trusted constraints and performance.
Unless you did some solid measurements that demonstrated that the constraint verification of the DELETE operation are a performance bottleneck, let the engine do its work.
Do not under any circumstances disable the constraints. This is an extremely stupid practice. You cannot maintain data integrity if you do things like this. Data integrity is the first consideration of a database because without it, you have nothing.
The correct method is to delete from the child tables before trying to delete the parent record. You are probably timing out because you have set up cascading deltes which is another bad practice in a large database.
I know this is an old thread, but I landed here when my row deletes were blocked by foreign key constraints. In my case, my table design permitted "NULL" values in the constrained column. In the rows to be deleted, I changed the constrained column value to "NULL" (which does not violate the Foreign Key Constraint) and then deleted all the rows.
I wanted to delete all records from both tables because it was all test data. I used SSMS GUI to temporarily disable a FK constraint, then I ran a DELETE query on both tables, and finally I re-enabled the FK constraint.
To disable the FK constraint:
expand the database object [1]
expand the dependant table object [2]
expand the 'Keys' folder
right click on the foreign key
choose the 'Modify' option
change the 'Enforce Foreign Key Constraint' option to 'No'
close the 'Foreign Key Relationships' window
close the table designer tab
when prompted confirm save changes
run necessary delete queries
re-enable foreign key constraint the same way you just disabled it.
[1] in the 'Object Explorer' pane, can be accessed via the 'View' menu option, or key F8
[2] if you're not sure which table is the dependant one, you can check by right clicking the table in question and selecting the 'View Dependencies' option.
This is the way to disable foreign key checks in MySQL. Not relevant to OP's question since they use MS SQL Server, but google search results do turn this up so here's for reference:
SET FOREIGN_KEY_CHECKS = 0;
/ Run your script /
SET FOREIGN_KEY_CHECKS = 1;
See if this helps, This is for ignoring the foreign key checks.
But deleting disabling this is very bad practice.
On all tables with foreign keys pointing to this one, use:
ALTER TABLE MyOtherTable NOCHECK CONSTRAINT fk_name
You can disable all of the constaints on your database by the following line of code:
EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
and after the runing your update/delete command, you can enable it again as the following:
EXEC sp_MSforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
You could maybe disable and re-enable constraints:
http://sqlforums.windowsitpro.com/web/forum/messageview.aspx?catid=60&threadid=48410&enterthread=y
For the testing purpose only, I used the following command in MySQL to delete only one record from a table that has foreign key references.
SET FOREIGN_KEY_CHECKS = 0; -- Disabling foreign key checks before running the following query.
DELETE FROM table_name WHERE id = id_to_delete; -- Deleting a record from a table that has foreign key reference.
SET FOREIGN_KEY_CHECKS = 1; -- Enabling foreign key checks after running the above query.
Temporarily disable constraints on a table T-SQL, SQL Server
MSSQL
ALTER TABLE TableName NOCHECK CONSTRAINT ALL
ALTER TABLE TableName CHECK CONSTRAINT ALL
ALTER TABLE TableName NOCHECK CONSTRAINT FK_Table_RefTable
ALTER TABLE TableName CHECK CONSTRAINT FK_Table_RefTable
ref
DELETE FROM TableName
DBCC CHECKIDENT ('TableName', RESEED, 0)
MySql
SET FOREIGN_KEY_CHECKS = 0; -- Disable foreign key checking.
TRUNCATE TABLE [YOUR TABLE];
SET FOREIGN_KEY_CHECKS = 1;

Resources