Cannot insert duplicate key row in object 'dbo.TitleClient' with unique index 'XAK1TitleClient' - sql

Ever since I cleaned the data on the SQL Database I've been getting this issue, whereas on the unclean database the issue does not happen. When I run my stored procedure (huge procedure) it returns:
General SQL error. Cannot insert duplicate key row in object 'dbo.TitleClient' with unique index 'XAK1TitleClient'. Cannot insert the value NULL into column 'id_title', table 'Database.dbo.TitleCom'; column does not allow null, insert fails.
Is it possible that I deleted data from a table that causes this? Or is that impossible?

Does dbo.TitleClient have an identity column? You might need to run
DBCC CHECKIDENT('dbo.TitleClient')
I'm guessing that the first message
Cannot insert duplicate key row in
object 'dbo.TitleClient' with unique
index 'XAK1TitleClient'
is because the seed value is out of synch with the existing table values and the second error message
Cannot insert the value NULL into
column 'id_title', table
'Database.dbo.TitleCom' column does
not allow null, insert fails.
Comes from a failed attempt at inserting the result of scope_identity from the first statement.

How cleanly did you "clean" the data?
If some tables still have data, that might be causing a problem.
Especially if you have triggers resulting in further inserts.
For you to investigate further.
Take the body of your stored proc, and run it bit-by-bit.
Eventually, you'll get to the actual statement producing the error.
Of course if you aren't inserting into dbo.TitleClient at this point, then it's certainly a trigger causing problems.
Either way: Now you can easily check the data inserted earlier in your proc to figure out the root cause.

Related

SQL Server, Using a stored procedure to insert data

I'm trying to insert data into my database by using a stored procedure but 3 of my columns are using the int identity type and I cannot insert. It keeps saying cannot do this whilst identity insert is off
When IDENTITY_INSERT is on, it just means that you can put your own data in IDENTITY column. It doesn't disable the FK constraint you have on the table. You can delete the FK constraint, or disable it, and risk having logically inconsistent data in your DB, or you can fix your SP so you won't insert any duplicate values.
Something is amiss. Three columns in a single table of type Identity? I'm having difficulty imagining what they could represent, and I have to wonder where the natural keys are.
In any case, IDENTITY_INSERT isn't something you want to putz with casually. It's an administrative feature to allow ad hoc changes to the data, for example bulk loading the database.
If you do actually know what the identities are (as input to your stored procedure) then the table is misdefined, because it's supposed to be the identity source. If you don't know, or you're willing to let the table generate identity values, then you simply don't mention those columns in your INSERT statement. At most, the generated values would be OUTPUT parameters to your stored procedure.

get Primary Key from SP

With SQL, when inserting values into a Table from a SP, is it possible to get the value of the Primary Key before the values are added to the Table?
This is certainly possible, leveraging the power of relational databases. Assuming, like Martin Smith said, that you are using an autogenerated key, then you can use a transaction to do what you're looking for.
Here's the general idea:
Start a transaction.
Do the insertion.
Use the primary key to do whatever you need to do, including updated the inserted row to reflect the value.
Commit or rollback
By beginning a transaction before your insert, you can assure that no one else will be able to see the new rows until you commit your transaction. If the key is not to your liking, you can rollback the transaction, and no one else will know. If the key is adequate, you can modify the rows you have just inserted before committing.
Since you have a transaction, no one else can see the intermediate data you have inserted before you commit. Thus, you can update the rows that you have just inserted as if you have the primary key before your actual insert.
If you are using SQL Server the best way to do this is with your MERGE or INSERT command use the OUTPUT clause to get your key back. Even though this is not before the insert you can use the results of the OUTPUT to join back the results of your data to insert subsequent children records.
Also if you are using SQL server you can look at IDENT_CURRENT function which will return the current identity value of a table. If you are writing your SQL in a set based fashion the OUTPUT that I mention above works best for me.

sql server, composite keys - ignoring duplicate

Is there a way to prevent sql from throwing an error when I try to save a record that already exists. I've got a composite key table for a many-to-many relationship that has only the two values, when I update a model from my application, it tries to save all records, the records that already exist throw an error Cannot insert duplicate key is there a way of having the database ignore these, or do I have to handle it in the application?
you are calling an INSERT and trying to add duplicated keys. This error is by design, and essential. The DB is throwing an exception for an exceptional and erroneous condition.
If you are, instead, trying to perform an "upsert" you may need to use a stored procedure or use the MERGE syntax.
If, instead, you don't want to UPDATE but to just ignore rows already in the table, then you need to simply add an exception to your INSERT statement... such as
....
WHERE
table.Key <> interting.key
Try something like this with your insert statement.
insert into foo (x,y)
select #x,#y
except
select x,y from foo
This will add a record to foo, ONLY if it is not already in the table.
You could try creating your index with the IGNORE_DUP_KEY option so that you only get a warning when you have duplicate keys rather than a true error.
The other option and possibly the better one is to use the MERGE statement rather than insert. The MERGE statement let's you do Inserts, Updates and Deletes all in one statement and sounds like it should work out well for what you are trying to do.
Last but not least, as you said fix it in your app and only insert the rows that need to be added.

SQL Server 2008 - Identity Column Skipped a Row ID

I have never seen this before, the rows will be sequential but I have noticed that it skipped over a particular "ID".... 1 2 3 4 6 7 8... missing 5...
There are no transactions in the INSERT stored procedure so nothing to roll back
We do not allow the deletion of records.
What else can be the case?
Probably a failed insert due to some other unique constraint on the table or a foreign key reference in the table and you try to insert an invalid fk value.
The insert doesn't have to be in a transaction.
The identity value increments even on a failed insert.
Igor mentions an important point about identities and transactions. From the docs:
Failed statements and transactions can
change the current identity for a
table and create gaps in the identity
column values. The identity value is
never rolled back even though the
transaction that tried to insert the
value into the table is not committed.
For example, if an INSERT statement
fails because of an IGNORE_DUP_KEY
violation, the current identity value
for the table is still incremented.
Any way, identity counter does not restore your value (if you have executed with transaction or without it). The same behavior has oracle (sequences).
Identity is not transactional.
You may use your own primary key counter and control access to it.
Failed attempts generates an identity value even though it is not inserted into the data table. Then, this results to the lost of an identity (it's a shame I can no longer find the post where I have learned it!).

What could cause an IDENTITY column to become corrupted?

I had an unusual problem yesterday where I was suddenly unable to insert records into a table with an identity column.
A simple insert like this: INSERT INTO MyTable (Column1, Column2) VALUES ('text', 236764)
Started throwing a primary key constraint violation.
I ran DBCC CHECKIDENT on the table, and realized that SQL Server had stopped updating the last used value, so that when it was inserting it was incrementing using the old value and the new identity value usually already existed in the table, hence the violation errors.
Resolving the problem wasn't an issue, I just reseeded the table for the next highest sequence number, but I've never seen this happen before!
Does anyone have any idea what might cause SQL Server to stop updating identity properties, and where I might look for evidence? There is no replication or any triggers involved, it's just a plain old table.
EDIT: SQL Log Rescue would have been ideal, but it only works on SQL Server 2000. Is there a similar tool out there for SQL 2005 logs?
If someone has inserted to the table using SET IDENTITY_INSERT ON, someone could absolutely have entered in an invalid value for the table. That would be my first guess. You could use a log analyzer like SQL Log Rescue to go back in time through the transaction logs and see if you could find who the bad person was who messed up your data...
I think SET IDENTITY_INSERT ON reseeds the Identity.
From BOL
If the value inserted is larger than
the current identity value for the
table, SQL Server automatically uses
the new inserted value as the current
identity value.
The only way I could reproduce this issue was to manually set the seed too low with DBCC CHECKIDENT.