June 5, 2006 at 1:18 am
Hi All
I am working on SQL Server 2000 using C#.NET 2003 and VB6.
I have 1 Stored Procedure which takes input parameters and does an insert to a table. This stored Procedure is called by the 2 applications mentioned above.
Here is the error which i get, which occures anytime which is not certain. I mean one fine day this error will start and No more records can be inserted into the Table unless last record is deleted.
-2147217900
[Microsoft][ODBC SQL Server Driver][SQL Server]Violation of PRIMARY KEY constraint 'PK_Transactions'. Cannot insert duplicate key in object 'Transactions'.
Couldnt understand what starts this problem
BELOW is the Stored Procedure (Sorry for the huge detail)
CREATE PROCEDURE TransactionRegister
@Transaction_Date datetime,
@Transaction_Time varchar(20),
@ItemShrtName varchar(30),
...[SOME MORE variables]
@Bill_AmountTotalFC float,
@FuelTransTerminalID varchar(50),
@TransCurrencyCode varchar (5),
@TransCurrencyExRt float,
@Identity int OUT
AS
BEGIN
Declare @costprice float
Declare @batchno varchar(20)
Select TOP 1 @costprice=PackPrice, @batchno=BatchNumber
from StockBatches
Where ItemCode=@ItemCode AND StoreCode=@StoreCode
ORDER BY AddTime Desc
Insert Into Transactions
(
Transaction_Date,
Transaction_Time,
ItemShrtName,
ItemCode,
...[Some More columns]
Bill_AmountTotalFC,
TransCurrencyCode,
TransCurrencyExRt,
Transaction_Code,
ItmCostPrice,
ItmBatchNoRef)
Values
(@Transaction_Date ,
@Transaction_Time,
@ItemShrtName,
@ItemCode,
...[SOME VALUES]
@Bill_AmountTotalFC,
@TransCurrencyCode,
@TransCurrencyExRt,
'TMP'+@storecode + RTrim(CAST(@poscode as char)), @costprice, @batchno)
SET @Identity = SCOPE_IDENTITY()
DECLARE @Temp varchar(50)
set @Temp= 'TRN'+@StoreCode+RTRIM(CAST(@PosCode AS char))+RTrim(CAST(@Identity AS char))
UPDATE Transactions SET Transaction_Code=@Temp WHERE Transaction_No=@Identity
END
GO
Rakesh Salian
June 5, 2006 at 5:25 am
I'm presuming that it is the identity column on the Transactions table that is the primary key in question?
When you "no more records can be inserted," do you mean inserted by any means, or inserted via this stored procedure?
June 5, 2006 at 10:15 pm
Yes the Primary key is in the Transactions Table and is an Auto Number(Identity column). And it is not possible to enter any more records via any means unless i delete the last record in the table.
Rakesh Salian
June 6, 2006 at 12:58 am
Is it possible that there's an insert into the transaction table from somewhere else, with identity_insert switched on?
It almost sounds like someone's inserting the 'next' transaction and manually assigning the pk value and when SQL generates the next identity value it's already in the table.
It might be worth running profiler for a while, see if you can see what starts the problem.
Also, check to make sure you've not got any database corruption. (DBCC CHECKDB)
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
June 6, 2006 at 3:47 am
When this occurs, use
DBCC
CHECKIDENT ('table_name', NORESEED)
to see if a value higher than the current identity value has been inserted, as suggested by GilaMonster above.
The results of this vary, so you should ignore the standard message and just look at the numbers. If the first number is less than the second, a record has been inserted in this way and your identity value is out of sync with the data values.
If you need to correct the problem again, you can run
DBCC CHECKIDENT ('table_name', RESEED)
But of course this is only a firefighting tactic and you need to search all app code including TSQL code for use of SET IDENTITY INSERT, then check whether it is using only recycled values from deleted records, and if not change it to use a normal identity insert and SCOPE_IDENTITY().
There is one circumstance in which this is not an adequate solution - if apps need to insert multiple records in a single INSERT statement and still know what the generated keys will be. In this case, you need to get rid of the identity property on the column and create a one-row, one column table containing an integer representing the last, or next, available PK value. It doesn't matter which as long as you are clear about it!
You then need to write a stored proc whih people can use to read and update this value (i.e.table) in transaction (you may as well force TABLOCKX) to reserve a range of keys before using that range in an INSERT.
This is a bit more wasteful of integers than an identity column, since the values reserved might not be used if the insert fails or is abandoned, but it does allow multiple-row inserts with known id values.
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
June 8, 2006 at 1:19 am
Firstly thanks to you all for helping me out.
I tried what stax68 & GilaMonster mentioned regarding the DBCC but the 2 numbers i get is same (test machine with same DB backup). Also i checked all the code and scripts which works with the table and non inserts identity key as all use this same stored procedure. Still test is underway as this occures suddenly so kept it under test to generate the same senario as it would be on the deployed site.
If possible i would like to know is there any way to find if this identity key ever changed or was our of sync. As i want to find a work around soon because generation of the same error would take some time on the test envoirnment.
Rakesh Salian
June 8, 2006 at 4:34 am
I'd set up a Profiler trace, filtering for the Transaction table, to record the sequence of events that lead up to the error happening. This should give you some clues as to what's going on.
June 8, 2006 at 12:35 pm
could you script out the PRIMARY KEY constraint and post the DDL? I have an idea... and you definitely ran DBCC with NORESEED first, before RESEED?
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply