----------
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.
Related
I need to store some records in a table. It's crucial the records must be unique. All duplicates must be silently ignored.
I wrote a procedure which accepts a user-defined table type, I send a record collection to it, and I try to have NEW, UNIQUE records stored.
How do I determine unique? I calculate SHA1 from a couple of columns. In my table, I have a Hash column. It has UNIQUE index constraint.
Here comes the tricky part. Instead of using IF EXIST(SEELCT ..) I use TRY / CATCH blocks, I let the INSERT silently fail on duplicate hash.
So I use cursor to fetch my rows, then I calculate the hash for each row, then I try to insert this row. If it fails, the next row is processed.
It works. It's quite fast. However I'm very disappointed with my identity column.
If I try to enter 3 identical records and 1 new one I get following id-s: 1, 4. I would expect 1 and 2, not 1 and 4. So identity is incremented on each failed insert. I need to avoid it.
I tried to wrap the INSERT into TRANSACTION and ROLLBACK in the CATCH block. It does nothing. It works, just the id-s are wrong.
Is there a way to use UNIQUE constraint to filter the duplicates efficiently or the only way is using IF EXISTS method?
Is using UNIQUE constraint really faster than IF EXISTS?
UPDATE:
The typical scenario would look like 1000 duplicates and 2 new rows. There will be some concurrent calls to this procedure. I just don't want it to slow the server considerably when I'll have like a couple of millions of rows in my table.
you can use SET IDENTITY INSERT and control that identity field till the end of insert:
SET IDENTITY INSERT ON
CURSOR --increasing also counter for identity column and setting it during loop
SET IDENTITY INSERT OFF
By the way, are you sure you cannot avoid cursors?
You could use EXCEPT to get only the values that are not already existing and inserting them in only one statement, that would be definitely faster; just to give an idea:
INSERT INTO DestTable
SELECT * FROM (SELECT * FROM SourceTable
EXCEPT
SELECT * FROM DestTable)
I have a 'change history' table in my SQL Server DB called tblReportDataQueue that records changes to rows in other source tables.
There are triggers on the source tables in the DB which fire after INSERT, UPDATE or DELETE. The triggers all call a stored procedure that just inserts data into the change history table that has an identity column:
INSERT INTO tblReportDataQueue
(
[SourceObjectTypeID],
[ActionID],
[ObjectXML],
[DateAdded],
[RowsInXML]
)
VALUES
(
#SourceObjectTypeID,
#ActionID,
#ObjectXML,
GetDate(),
#RowsInXML
)
When a row in a source table is updated multiple times in quick succession the triggers fire in the correct order and put the changed data in the change history table in the order that it was changed. The problem is that I had assumed that the DateAdded field would always be in the same order as the identity field but somehow it is not.
So my table is in the order that things actually happened when sorted by the identity field but not when sorted by the 'DateAdded' field.
How can this happen?
screenshot of example problem
In example image 'DateAdded' of last row shown is earlier than first row shown.
You are using a surrogate key. One very important characteristic of a surrogate key is that it cannot be used to determine anything about the tuple it represents, not even the order of creation. All systems which have auto generated values like this, including Oracles sequences, make no guarantee as to order, only that the next value generated will be unique from previous generated values. That is all that is required, really.
We all do it, of course. We look at a row with ID of 2 and assume it was inserted after the row with ID of 1 and before the row with ID of 3. That is a bad habit we should all work to break because the assumption could well be wrong.
You have the DateAdded field to provide the information you want. Order by that field and you will get the rows in order of insertion (if that field is not updateable, that is). The auto generated values will tend to follow that ordering, but absolutely do not rely on that!
try use Sequence...
"Using the identity attribute for a column, you can easily generate auto-
incrementing numbers (which as often used as a primary key). With Sequence, it
will be a different object which you can attach to a table column while
inserting. Unlike identity, the next number for the column value will be
retrieved from memory rather than from the disk – this makes Sequence
significantly faster than Identity.
Unlike identity column values, which are generated when rows are inserted, an
application can obtain the next sequence number before inserting the row by
calling the NEXT VALUE FOR function. The sequence number is allocated when NEXT
VALUE FOR is called even if the number is never inserted into a table. The NEXT
VALUE FOR function can be used as the default value for a column in a table
definition. Use sp_sequence_get_range to get a range of multiple sequence
numbers at once."
I have this relationship:
Where CurrentVersionID points to the current active version of the game.
In ArcadeGameVersion the GameID property points to the associated ArcadeGame record.
Problem is, I can't insert either record:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_ArcadeGame_ArcadeGameVersions". The conflict occurred in database "Scirra", table "dbo.ArcadeGameVersions", column 'ID'.
Is this a badly formed data structure? Otherwise what is the best solution to overcome this?
This structure can work if you need it to be this way.. assuming the IDs are identity fields, I believe you will need to do this in 5 steps:
Insert an ArcadeGame record with a null value for CurrentVersionId
Determine the ID value of the record just added, using a statement like: SELECT #arcadeGameId = SCOPE_IDENTITY()
Insert an ArcadeGameVersion record, setting the GameID to the value determined in the previous step
Determine the ID value of the record just added (again using SCOPE_IDENTITY())
Update the ArcadeGame record (where the ID matches that determined in step 2) and set the CurrentVersionId to the value determined in the previous step.
You will (most likely) want to do the above within a transaction.
If the IDs aren't identity fields and you know the values ahead of time, you can mostly follow the same steps as above but skip the SELECT SCOPE_IDENTITY() steps.
Seems badly formed. I can not see why you need this circular reference.
I would use only one table ArcadeGame with additional fields CurrentVersion and UploadDate.
You can query it based on UploadDate for example, up to your needs. If you explain what you want from that db, answer could be more specific.
I'd like to copy a table's row before updating and I'm trying to do it like this:
CREATE TRIGGER first_trigger_test
on Triggertest
FOR UPDATE
AS
insert into Triggertest select * from Inserted
Unfortunately, I get the error message
Msg 8101, Level 16, State 1, Procedure first_trigger_test, Line 6
An explicit value for the identity column in table 'Triggertest' can only be specified when a column list is used and IDENTITY_INSERT is ON.
I assume it's because of the id-column; can't I do something like 'except' id? I do not want to list all the columns in the trigger as it should be as dynamic as possible...
You can't, basically. You'll either have to specify the columns, or use a separate table:
CREATE TRIGGER first_trigger_test
on Triggertest
FOR UPDATE
AS
insert into Triggertest_audit select * from deleted
(where Triggertest_audit is a second table that looks like Triggertest, but without the primary key/identity/etc - commonly multiple rows per logical source row; not I assumed you actually wanted to copy the old values, not the new ones)
The problem happens because you are trying to set an identity column in Triggertest.
Is that your plan?
If you want to copy the new identity columns from INSERTED into Triggertest, then define the column in Triggertest without IDENTITY
If Triggertest has it's own IDENTITY columns, use this:
insert into Triggertest (col1, col2, col3) select col1, col2, col3 from Inserted
After comment:
No, you can't without dynamic SQL to detect what table and find all non-identity colums.
However, if you add or remove columns you'll then have a mis-match between trigger table and Triggertest and you'll get a different error.
If you really want it that dynamic, you'd have to concat all columns into one or use XML to ignore schema.
Finally:
Do all your tables have exactly the same number of columns and datatypes and nullability as TriggerTest... because this is the assumption here...
IF you want the table to be built each time the trigger runs then you have no choice but to use the the system tables to find the columns and create a table with those column definitions. Of course your first step will have to be to drop the existing table or the trigger won't work the second time someone updates a record.
However, I think you need to rethink this process. Dropping a table then creating a new one every time you change a record is a seriously bad idea. How is this table in anyway useful when it may get wiped out and rebuilt every second or so?
What you might consider doing instead is create a dynamic process to create the Create trigger scripts that have the correct information for that table but which are not dynamic. Then your configuration people need to run this process every time table changes are made.
Remember it is critical for triggers to do two things, run as fast as humanly possible and account for proccesing all the records inthe batch (triggers should never have row-by-row proccessing or other slow processses or assume only one row will be in inserted or deleted tables) Dynamic SQL in a trigger is porbably also a bad idea as you can't test out all the possibilites beforehand and can bring your whole production server to a screaming halt when some unexpected thing happens.
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.