Empty table data and reset IDENTITY columns - database

I created a database in SQL Server with a couple of tables. I ran some tests and now am ready to deploy my solution, problem is, there is all sorts of data in the tables. I want to delete every row of all the tables created with my tests and put back the primary keys to zero. I tried delete which doesn't reset the primary keys index, and drop simply destroyed the table.

You can try TRUNCATE TABLE which deletes all rows and resets identity seeds. However you will have to execute in a certain order if you have foreign keys. In which case you will need to delete from the child tables first, or drop the constraints and re-add them.
Also note that if you are using IDENTITY you really shouldn't expect the numbers to mean anything, or to be generated forever without gaps. You shouldn't care whether it starts at 1 vs. 22 or 65 - can you explain why the identity values need to be reset?

From: http://www.howtogeek.com/howto/database/reset-identity-column-value-in-sql-server/
To set the value of the next ID to be 1, I can use this command:
DBCC CHECKIDENT (orders, RESEED, 0)

Related

Avoiding gaps in an identity column

I have a table in MS SQL SERVER 2008 and I have set its primary key to increment automatically but if I delete any row from this table and insert some new rows in the table it starts from the next identity value which created gap in the identity value. My program requires all the identities or keys to be in sequence.
Like:
Assignment Table has total 16 rows with sequence identities(1-16) but if I delete a value at 16th position
Delete From Assignment Where assignment_id=16;
and after this operation when I insert a new row
Insert into Assignment(assignment_title)Values('myassignment');
Rather than assigning 16 as a primary key to this new value it assigns 17.
How can I solve this Problem ?
Renaming or re-numbering primary key values is not a good database management practice. I suggest you keep the primary key as is, and create a separate column index with the values you require to be re-numbered. Then simply create a trigger to run a routine that will re-number every row in the order you expect, obviously by seeking the "gaps" and entering them with values incremented from their previous value.
This is SQL Servers standard behaviour. If you deleted a row with ID=8 in your example, you would still have a gap.
All you could do, is write a function getSmallestDreeID in SQL Server, that you called for every insert and that would get you the smallest not assigned ID. But you would have to take great care of transactions and ACID.
The behavior you desire isn't possible without some post processing logic to renumber the rows.
Consider thus scenario:
Session 1 begins a transaction, inserts a row (id=16), but doesn't commit yet.
Session 2 begins a transaction, inserts a row (id=17) and commits.
Session1 rolls back.
Whether 16 will or will not exist in the table is decided after 17 is committed.
And you can't renumber these in a trigger, you'll get deadlocked.
What you probably need to do is to query the data adding a row number that is a sequential integer.
Gaps in identity values isn't a problem
well, i have recently faced the same problem: i need the ID values in an external C# application in order to retrieve files named exactly as the ID.
==> here is what i did to avoid the identity property, i entered id values manually because it was a small table, but if it is not in your case, use a SEQUENCE SQL Server 2014.
Use the statement UPDATE instead of delete to keep the id values in order.

are there any options for doing bulk-insert to multiple related tables with entity framework (sql server 2008 r2 target)?

There are existing options for doing bulk insert into a single table with EF entities. Specifically, this SO question and using this class from David Browne.
In the case of trying to bulk insert rows into both a parent and child table, however, nothing jumps out as an option at that same level of convenience.
The 'hacks' I can think of (but I'm hoping there's at least one better option out there) include:
generate the PK's and set the FK's before insert (in this scenario, we know nothing else is inserting at the same time), then do the bulk inserts of both (turning off IDENTITY_INSERT during the parent insert if necessary)
bulk insert (using the linked SO question's approach) the parent rows, select them (enough columns to identify which parent row is which), generate child rows, bulk insert those
generate the sql necessary to insert all the rows in a single batch, doing each parent and then all related children, using ##identity to fill in the FK for the child inserts
The 'pregenerate PK values' approach (I haven't actually tried it) seems fine, but is fragile (requires no other inserts to at least parent during the operation) and depends on either an empty table or selecting max(pk)+1 beforehand.
Since SqlBulkCopy seems to be built around inserting a table at a time (like bcp), anything that still lets sql generate the PK/identity column would seem to be built around 'dropping down' to ado.net and building the sql.
Is there an option outside of 'generate the tons of sql' that I'm missing? If not, is there something out there that already generates the sql for mass-insert into related tables?
Thanks!!
The first rule of any foreign key constraint is that it must exist, as a primary key or unique constraint, in another table before inserted into the foreign key table.
This works great when you are adding a few rows at a time (traditional transaction processing environment). Howevere, you are trying to bulk insert into both at the same time. I'd term this as batch processing. Basically, the bulk update lock on the parent table is going to block the child table from reading it to check that the fk linkage is valid.
I'd say your 2 options would be 1.) leave the fk out entirely or 2.) Set the fk as nocheck before the bulk insert, then turn the check on after the bulk insert is complete with an alter table.

How to insert empty record in a table

----------
ID NAME
3 A
4 B
5 C
----------
when i delete all record, it continues after number five's record, but i want it must be insert first index of this table. can anyone help me?
I assume you've got your ID column as an IDENTITY column, and you want to reset it to start again at 1, after having removed all rows from the table.
First, I'd say that having such a need (that the ID value start at 1) tends to mean there's something wrong with what you're doing - IDENTITY columns can always have gaps in the numbering, and should be treated as opaque blobs. The fact that they appear to be integers, and tend to be easy to remember, are just implementation details.
Second, if you want to do such a reset, you'd use DBCC CHECKIDENT
Edit
If you really do depend on these ID values (say, because they're also used in an application), it's a good indicator that the column shouldn't have the IDENTITY property in the first place. Unfortunately, you can't directly remove this property - you'd have to create a copy of the table without this property, copy all rows across, delete the original table, and rename the copy. Management Studio will pretend you can just remove the property, but will do what I've just described behind the scenes.
A simple way would be to
TRUNCATE TABLE mytable;
instead of
DELETE FROM mytable
From TRUNCATE TABLE (Transact-SQL)
If the table contains an identity column, the counter for that column is reset to the seed value defined for the column. If no seed was defined, the default value 1 is used. To retain the identity counter, use DELETE instead.
Looks like your ID column is an IDENTITY column - these will always add the next value (regardless of deletes).
The requirement to have a specific ID does sound like your application design relies on it, which is not good practice. ID fields do have gaps (which is normal) - your application shouldn't rely on them.
Regardless, here are a couple of ways of doing this:
For a one off, use SET IDENTITY INSERT ON:
SET IDENTITY INSERT dbo.myTable ON
INSERT INTO myTable
(ID, NAME)
VALUES
(1, 'H')
SET IDENTITY INSERT dbo.myTable OFF
To reset the seeding, you need to use a DBCC CHECKIDENT command, using RESEED:
DBCC CHECKIDENT('myTable', RESEED, 0)
I think you want to restart the value of the autogenerated id column with 1 again?
if it is an IDENTITY column, you can reset the seed value with teh following command
DBCC CHECKIDENT('YourTableNameHere', RESEED, 0)
Databases ID feature are intended to go sure different records will NEVER have the same ID. This is not only valid for records existing at the same time, but also for new records being inserted after another one was deleted. This is extremely useful to avoid conflicts. Although it seems to sometimes break some people's sense of taste don't work around it.
If you need to assign self chosen numbers to the records add another column. Auto-indexed columns should be used all the time. The other users told you how to fiddle with the index but use this feature very careful.

Making primary key and identity column after data has been loaded

I have quick question for you SQL gurus. I have existing tables without primary key column and Identity is not set. Now I am trying to modify those tables by making existing integer column as primary key and adding identity values for that column. My question is should I first copy all the records from the table to a temp table before making those changes . Do I loose all the previous records if I ran the T-SQL commnad to make primary key and add identity column on those tables. What are the approaches should I take such as
1) Create temp table to copy all the records from the table to be modified
2) Load all the records to the temptable
3) Make changes on the table schema
4) Finally load the records from the temp table to the original table.
Or
there are better ways that this? I really appreciate your help
Thanks
Tools>Options>Designers>Table and Database Designers
Uncheck "Prevent saving changes that require table re-creation"
[Edit] I've tried this with populated tables and I didn't lose data, but I don't really know much about this.
Hopefully you don't have too many records in the table. What happens if you use Management studio to change an existing field to identity is that it creates another table with the identity field set. it turns identity insert on and inserets the records from the original table, then turns identity insert off. Then it drops the old table and renames the table it just created. This can be quite a lengthy process if you have many records. If so I would script this out and then do it in a job that runs during the off hours because the table will be completely locked while you do this.
just do all of your changes in management studio, copy/paste the generated script into a file. DON'T SAVE CHANGES at this point. Look over and edit that script as necessary, it will probably do almost exactly what you are thinking (it will drop the original table and rename the temp one to the original's name), but handle all constraints and FKs as well.
If your existing integer column is unique and suitable, there should be no problem converting it to a PK.
Another alternative, if you don't want to use the existing column, you can add a new PK columns to the main table, populate it and seed it, then run update statements to update all other tables with new PK.
Whatever way you do it, make sure you do a back-up first!!
You can always add the IDENTITY column after you have finished copying your data around. You can also then reset the IDENTITY seed to the max integer + 1. That should solve your problems.
DBCC CHECKIDENT ('MyTable', RESEED, n)
Where n is the number you want the identity to start at.

Is there a way to reset the IDENTIY column in sql server? and would this be a reason not to use an Identity Column?

I have a development database that has fees in it. It has a feeid, which is a unique key that is the identifier. The problem I run into is that the feeid/fee amount may not match when putting updating the table on a production server. This obviously could lead to some bad things happening, like overcharging for something or undercharging. Is there a way to match reset identities in sql server or match them or is this an example of when you would not want to use them?
Don't make your primary keys
"mean something" other than
identifying an unique record. If you
need to hard code an ID somewhere,
create another column for it.
So-called "natural keys" are more
trouble than they're worth
If,
for some reason, you decide that
either you will not or cannot follow
the first rule, don't use any
automatically generated key values.
That is the behaviour of an identity column, this is also what makes it so fast because it doesn't lock the table
to reset an identity either use DBCC CHECKIDENT or TRUNCATE TABLE
to insert IDs from one table to another and to keep the same values you need to do
SET IDENTITIY_INSERT ON
--upddate/insert rows
SET IDENTITIY_INSERT OFF
keep in mind that during the time between the two SET IDENTITIY_INSERT statements that your regular inserts will FAIL!
You can set IDENTITIY INSERT ON, update the IDs (make sure there are no conflicts) and then turn it back off.

Resources