February 5, 2007 at 8:46 am
I can't imagine this is a new concept, but a search here didn't seem to turn up anything relevant.
I have a screwy database and crappy data coming in, just so you know up front. Nothing I can do about either at this point, which is why I am trying to build in error handling and recovery in my procedure.
I have to do inserts into 4 tables with data being selected from another database, for new recruits. There will be multiple records coming from the other DB, and I must maintain relationships as I do the insert.
I am using a cursor loop though the list of recruits, pulling each recruit's info from the source DB and insert it into the destination tables. Sometimes I get a duplicate record on the Select (remember the crappy data part?). I'd like to use a transaction to fail one recruit's inserts, but go on to the next recruit even though the previous failed.
My error handling looks like this:
Open PCursor
Fetch Next From PCursor Into @SS
While @@Fetch_Status <> -1
Begin
Select @ErrorNum = 0
Begin Transaction InsertNewEmp
<all the inserts for the recruit>
The following line goes after each SQL statement during the inserts.
Select @ErrorNum = @ErrorNum + @@Error
At the end of the inserts I do this:
If @ErrorNum > 0
Begin
ROLLBACK TRANSACTION InsertNewEmp
Print 'Error: ' + Convert(VarChar(15), @ErrorNum)
--Return @ErrorNum
End
Else
Begin
Commit Transaction InsertNewEmp
End
Fetch Next From PCursor Into @SS
End
I was hoping this would allow me to roll back all inserts for the one recruit if any insert failed, but when I run it, and it encounters the first error, first it does not handle the error correctly, because it completes the insert into the other tables, and second, it loops through to the next iteration of the cursor, the next recruit, and does the same thing, except it no longer inserts records in any table.
I'm doing Inserts into 4 tables, and another routine for each table to figure out the ID I need to insert into the primary key (remember the screwy DB?).
Here are some results from troubleshooting Prints I put into the code.:
AppBaseID= 282381
SS: 5494
AppEEO
AppEEOID= 153525548
ReqBase
ReqID= 165391969
Server: Msg 2627, Level 14, State 1, Line 132
Violation of PRIMARY KEY constraint 'PK_ReqBase_RbFlxID'. Cannot insert duplicate key in object 'ReqBase'.
The statement has been terminated.
AppToReqID= 165391970
Error: 2627
I have been reading about "Save Transaction <tran name>", but I have not been able to figure out if that is relevant to this situation since I want to either commit or rollback every statement inside a single iteration of a cursor.
I know this is confusing. Let me know what more info you need.
Thanks,
Chris
February 5, 2007 at 9:32 am
I doubt if you need to use a cursor for this. Why not just do a batch insert of everything in the correct order with the INSERT queries getting rid of the duplicates? If you have a large amount of data the inserts can be done in batches.
If you really want to use a cursor, I suspect the problem could be with the naming of the transactions. Try just using BEGIN TRAN, COMMIT and ROLLBACK.
February 5, 2007 at 10:59 am
I'd rather not use a cursor, whenever possible, but I have been unable to think of a way to do this without it. You see, in order to maintain data integrity, I must grab the ID created on the first insert and use it for the later inserts, and on top of that, these tables do not have Identity fields for the primary key. They are Int, but not Identity, and the way this vednor chose to do it is to keep the current latest ID value for X table in another table, so when I need to get an ID, I go to the other table, find out what the ID value for X table is, increment it, update the other table, then use that same value to do the insert into table X. This must happen for each of the 4 tables I am inserting into. This is another reason I want my transaction to work, so that the ID value does not get incremented if the insert fails.
The only logical reason I have been able to come up with for this design is because this DB must be supportable across different platforms, but I would think that all platforms would be able to have an Identity type of field in them, so maybe we are talking legacy too.
I will try removing the naming of the transaction now
Thanks,
Chris
February 5, 2007 at 11:20 am
The removal of the name did not help.
Here is the entire source of the procedure:
Declare @AppBaseID Int
Declare @AppID Int
Declare @AppEEOID Int
Declare @RBID Int
Declare @AppToReqID Int
Declare @SS VarChar(15) --Social Security Number.
Declare @ErrorNum Int
Set NoCount ON
Set Xact_Abort OFF
Declare PCursor Cursor Fast_Forward For
Select Replace(P.SS, '-', '')
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Where S.Status = 'Hired'
And C.CostCenterNum <> '99999'
And S.Current_Emp <> 1
And S.Former_Emp <> 1
And (P.SS Is Not Null And LTrim(P.SS) <> '') --Must not have blank SSN.
And Replace(P.SS, '-', '') Not In(Select apSocNum From VHR_DataSQL.dbo.AppBase)
And S.StatusDate > DateAdd(d, -5, GetDate())
Select @AppID = Max(apAppID) + 1 From AppBase
Open PCursor
Fetch Next From PCursor Into @SS
While @@Fetch_Status <> -1
Begin
Select @ErrorNum = 0
Begin Transaction
--Get new FlxID for AppBase table.
Select @AppBaseID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppBase'
Update TH
Set TH.thNumber = @AppBaseID
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppBase'
Select @ErrorNum = @ErrorNum + @@Error
Print 'Table AppBase' --For troubleshooting
Print 'AppBaseID= ' + Convert(Char(15),@AppBaseID) --For troubleshooting
--Insert to AppBase.
Insert Into VHR_DataSQL.dbo.AppBase
(apFlxID, apFirstName, apLastName, apSocNum, apStreet1,
apStreet2, apCity, apState, apZip, apHomePhone, ApEMail,
ApStatus, apCountry, apUserName, apAppID)
Select
@AppBaseID, Left(S.FirstName, 20), Left(S.LastName, 20),
Left(Replace(P.SS, '-', ''), 9), Left(S.Address, 35), Left(S.Address2, 35), Left(S.City, 35),
Left(S.State, 35), Left(S.Zip, 10),
Left(Replace(S.Phone, '-', ''), 14), Left(S.Email, 64),
Left(J.Type, 30),
'USA', 'RMSImportProcess',
S.Submit_ID
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Where Replace(P.SS, '-', '') = @SS
Print 'SSN: ' + @SS
Select @ErrorNum = @ErrorNum + @@Error
--Get FlxID for AppEEO table.
Select @AppEEOID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppEEO'
Update TH
Set TH.thNumber = @AppEEOID
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppEEO'
Select @ErrorNum = @ErrorNum + @@Error
Print 'Table AppEEO' --For Troubleshooting
Print 'AppEEOID= ' + Convert(Char(15),@AppEEOID)
--Insert to the AppEEO table.
Insert Into AppEEO (aoFlxID, aoFlxIDap, aoDateBorn, aoSex, aoEthnic, aoVeteran, aoUserName,
aoDateBeg)
Select
@AppEEOID,
@AppBaseID,
Convert(DateTime, P.DOB),
ED.Sex,
Left(EP.Profile_Name, 30),
IsNull(ED.MilStatus, 'None'),
'RMSImportProcess',
GetDate()
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.EEODETAILEDTABLE ED On S.Submit_ID = ED.Submit_ID
Inner Join RMS.dbo.eeoProfiles EP On ED.Profile_ID = EP.Profile_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Inner Join VHR_DataSQL.dbo.AppBase AP On Replace(P.SS, '-', '') = AP.apSocNum
Where Replace(P.SS, '-', '') = @SS
Select @ErrorNum = @ErrorNum + @@Error
--Print 'ReqBase ID' --For Troubleshooting
--Get latest FlxID for ReqBase.
Select @RBID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'ReqBase'
Update TH
Set TH.thNumber = @RBID
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'ReqBase'
Select @ErrorNum = @ErrorNum + @@Error
Print 'Table ReqBase' --For Troubleshooting
--Insert to the ReqBase table.
Print 'ReqID= ' + Convert(VarChar(15),@RBID)
Insert Into ReqBase (rbFlxID, rbTitle, rbDateStart, rbDateEnd, rbSalary,
rbNewHireName, rbSupervisor, rbReqID, rbDivision, rbFlxIDjb,
rbSupervisorFlxIDeb, rbContactFlxIDeb, rbContact, rbUserName)
Select
@RBID,
Left(JL.JobTitle, 60),
Convert(DateTime,P.StartDate) AS StartDate,
Convert(DateTime,P.EndDate) AS EndDate,
Convert(Decimal(18,0), P.Salary),
Left(P.Sign_On, 40),
Left(M.FirstName + ' '+ M.LastName, 30) As ManagerName,
Left(J.REQ, 30),
Left(C.CostCenterNum, 30) As UnitNbr,
JB.jbFlxID,
M.[User_ID],
Case IsNumeric(U2.[User_Name])
When 1 Then U2.[User_Name]
Else Null
End as RecruiterID,
Left(U1.UserFirstName + ' ' + U1.UserLastName, 30) As Recruiter,
'RMSImportProcess'
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.JobLibrary JL On J.JobLibraryID = JL.JobLibraryID
Inner Join RMS.dbo.JobCodes JC On JL.JobCodeID = JC.JobCodeID
Inner Join RMS.dbo.Managers M On P.Man_ID = M.Man_ID
Inner Join RMS.dbo.Users U2 On M.Man_ID = U2.Man_ID
Inner Join RMS.dbo.Users U1 On M.[User_ID] = U1.[User_ID]
Inner Join RMS.dbo.tblBranchInfo BR On M.BranchID = BR.BranchID
Inner Join RMS.dbo.Clients CL On BR.BranchID = CL.BranchID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Inner Join VHR_DataSQL.dbo.JobCode JB On JB.jbJobCode = JC.JobCode
Inner Join VHR_DataSQL.dbo.AppBase AP On AP.apSocNum = Replace(P.SS, '-', '')
Where Replace(P.SS, '-', '') = @SS
Select @ErrorNum = @ErrorNum + @@Error
--Print 'AppToReq ID' --For Troubleshooting
--Get latest FlxID for the AppToReq table.
Select @AppToReqID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxID = FT.ftCounter
Where ftTblName = 'AppToReq'
Update TH
Set TH.thNumber = @AppToReqID
From Thing TH
Inner Join FlxTable FT On TH.thFlxID = FT.ftCounter
Where ftTblName = 'AppToReq'
Select @ErrorNum = @ErrorNum + @@Error
Print 'AppToReqID= ' + Convert(Char(15),@AppToReqID)
Print 'Table AppToReq' --For Troubleshooting
--Insert the necessary IDs from the AppBase and ReqBase tables to this link table.
Insert Into AppToReq (arFlxId, arFlxIDap, arFlxIDrb, arUserName)
Values(@AppToReqID, @AppBaseID, @RBID, 'RMSImportProcess')
Select @ErrorNum = @ErrorNum + @@Error
--SAVE TRANSACTION InsertNewEmp
If @ErrorNum <> 0
Begin
ROLLBACK TRANSACTION
Print 'Error: ' + Convert(VarChar(15), @ErrorNum)
--Return @ErrorNum
End
Else
Begin
Commit Transaction
End
Fetch Next From PCursor Into @SS
End
Close PCursor
DEALLOCATE PCursor
The errors returned look like this:
Table AppBase
AppBaseID= 282382
SSN: 5750
Table AppEEO
AppEEOID= 153525549
Table ReqBase
ReqID= 165391971
Server: Msg 2627, Level 14, State 1, Line 129
Violation of PRIMARY KEY constraint 'PK_ReqBase_RbFlxID'. Cannot insert duplicate key in object 'ReqBase'.
The statement has been terminated.
AppToReqID= 165391972
Table AppToReq
Error: 2627
Table AppBase
AppBaseID= 282382
SSN: 0486
Table AppEEO
AppEEOID= 153525549
Table ReqBase
ReqID= 165391971
Server: Msg 2627, Level 14, State 1, Line 129
Violation of PRIMARY KEY constraint 'PK_ReqBase_RbFlxID'. Cannot insert duplicate key in object 'ReqBase'.
The statement has been terminated.
AppToReqID= 165391972
The current problem is that one record is inserted into every table except the ReqBase, which has the primary key violation. The 2 problems here are 1. that one record is inserted into every other table but ReqBase, even though all of the insterts are contained withint 1 transaction, and 2. only one record gets inserted into each table, of those that any record gets insterted. I find this strange because the 3rd insert is where the failure occurs, but the 4th insert, on the first iteration, works, yet no other iterations happen, such as all of the records get inserted into all tables except the ReqBase table, where the primary key violation is.
My goal is to insert all records that do not violate a PK on any table, since I cannot count on my incoming data to be clean (I am trying to remedy the bad data with the vendor, but they just aren't getting it)
Thanks,
Chris
February 5, 2007 at 1:07 pm
OK, after thinking about it, I was able to eliminate the cursor. The transaction still does not work as expected though.
Here is the new source.
The results are still the same for the error messages, but the inserts act differently. Inserts for tables 1 and 2 work for the first record, and no others, no matter how many times I run the procedure. Inserts for table 3 never work due to the PK violation, and an insert happens for table 4 every time I run the procedure, but only for one insert.
Declare @AppBaseID Int
Declare @AppID Int
Declare @AppEEOID Int
Declare @RBID Int
Declare @AppToReqID Int
Declare @SS VarChar(15) --Social Security Number.
Declare @ErrorNum Int
Set NoCount ON
Set Xact_Abort OFF
Set @SS = 0
While @SS Is Not Null
Begin
Select @SS = Min(Replace(P.SS, '-', ''))
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Where S.Status = 'Hired'
And C.CostCenterNum <> '99999'
And S.Current_Emp <> 1
And S.Former_Emp <> 1
And (P.SS Is Not Null And LTrim(P.SS) <> '') --Must not have blank SSN.
And Replace(P.SS, '-', '') Not In(Select apSocNum From VHR_DataSQL.dbo.AppBase)
And S.StatusDate > DateAdd(d, -5, GetDate())
And Replace(P.SS, '-', '') > @SS
Select @ErrorNum = 0
Begin Transaction
--Get new FlxID for AppBase table.
Select @AppBaseID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppBase'
Update TH
Set TH.thNumber = @AppBaseID
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppBase'
Select @ErrorNum = @ErrorNum + @@Error
Print 'Table AppBase' --For troubleshooting
Print 'AppBaseID= ' + Convert(Char(15),@AppBaseID) --For troubleshooting
--Insert to AppBase.
Insert Into VHR_DataSQL.dbo.AppBase
(apFlxID, apFirstName, apLastName, apSocNum, apStreet1,
apStreet2, apCity, apState, apZip, apHomePhone, ApEMail,
ApStatus, apCountry, apUserName, apAppID)
Select
@AppBaseID, Left(S.FirstName, 20), Left(S.LastName, 20),
Left(Replace(P.SS, '-', ''), 9), Left(S.Address, 35), Left(S.Address2, 35), Left(S.City, 35),
Left(S.State, 35), Left(S.Zip, 10),
Left(Replace(S.Phone, '-', ''), 14), Left(S.Email, 64),
Left(J.Type, 30),
'USA', 'RMSImportProcess',
S.Submit_ID
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Where Replace(P.SS, '-', '') = @SS
Print 'SSN: ' + @SS
Select @ErrorNum = @ErrorNum + @@Error
--Get FlxID for AppEEO table.
Select @AppEEOID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppEEO'
Update TH
Set TH.thNumber = @AppEEOID
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'AppEEO'
Select @ErrorNum = @ErrorNum + @@Error
Print 'Table AppEEO' --For Troubleshooting
Print 'AppEEOID= ' + Convert(Char(15),@AppEEOID)
--Insert to the AppEEO table.
Insert Into AppEEO (aoFlxID, aoFlxIDap, aoDateBorn, aoSex, aoEthnic, aoVeteran, aoUserName,
aoDateBeg)
Select
@AppEEOID,
@AppBaseID,
Convert(DateTime, P.DOB),
ED.Sex,
Left(EP.Profile_Name, 30),
IsNull(ED.MilStatus, 'None'),
'RMSImportProcess',
GetDate()
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.EEODETAILEDTABLE ED On S.Submit_ID = ED.Submit_ID
Inner Join RMS.dbo.eeoProfiles EP On ED.Profile_ID = EP.Profile_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Inner Join VHR_DataSQL.dbo.AppBase AP On Replace(P.SS, '-', '') = AP.apSocNum
Where Replace(P.SS, '-', '') = @SS
Select @ErrorNum = @ErrorNum + @@Error
--Print 'ReqBase ID' --For Troubleshooting
--Get latest FlxID for ReqBase.
Select @RBID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'ReqBase'
Update TH
Set TH.thNumber = @RBID
From Thing TH
Inner Join FlxTable FT On TH.thFlxId = FT.ftCounter
Where ftTblName = 'ReqBase'
Select @ErrorNum = @ErrorNum + @@Error
Print 'Table ReqBase' --For Troubleshooting
--Insert to the ReqBase table.
Print 'ReqID= ' + Convert(VarChar(15),@RBID)
Insert Into ReqBase (rbFlxID, rbTitle, rbDateStart, rbDateEnd, rbSalary,
rbNewHireName, rbSupervisor, rbReqID, rbDivision, rbFlxIDjb,
rbSupervisorFlxIDeb, rbContactFlxIDeb, rbContact, rbUserName)
Select
@RBID,
Left(JL.JobTitle, 60),
Convert(DateTime,P.StartDate) AS StartDate,
Convert(DateTime,P.EndDate) AS EndDate,
Convert(Decimal(18,0), P.Salary),
Left(P.Sign_On, 40),
Left(M.FirstName + ' '+ M.LastName, 30) As ManagerName,
Left(J.REQ, 30),
Left(C.CostCenterNum, 30) As UnitNbr,
JB.jbFlxID,
M.[User_ID],
Case IsNumeric(U2.[User_Name])
When 1 Then U2.[User_Name]
Else Null
End as RecruiterID,
Left(U1.UserFirstName + ' ' + U1.UserLastName, 30) As Recruiter,
'RMSImportProcess'
From RMS.dbo.Submits S
Inner Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
Inner Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
Inner Join RMS.dbo.JobLibrary JL On J.JobLibraryID = JL.JobLibraryID
Inner Join RMS.dbo.JobCodes JC On JL.JobCodeID = JC.JobCodeID
Inner Join RMS.dbo.Managers M On P.Man_ID = M.Man_ID
Inner Join RMS.dbo.Users U2 On M.Man_ID = U2.Man_ID
Inner Join RMS.dbo.Users U1 On M.[User_ID] = U1.[User_ID]
Inner Join RMS.dbo.tblBranchInfo BR On M.BranchID = BR.BranchID
Inner Join RMS.dbo.Clients CL On BR.BranchID = CL.BranchID
Inner Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
Inner Join VHR_DataSQL.dbo.JobCode JB On JB.jbJobCode = JC.JobCode
Inner Join VHR_DataSQL.dbo.AppBase AP On AP.apSocNum = Replace(P.SS, '-', '')
Where Replace(P.SS, '-', '') = @SS
Select @ErrorNum = @ErrorNum + @@Error
--Print 'AppToReq ID' --For Troubleshooting
--Get latest FlxID for the AppToReq table.
Select @AppToReqID = thNumber + 1
From Thing TH
Inner Join FlxTable FT On TH.thFlxID = FT.ftCounter
Where ftTblName = 'AppToReq'
Update TH
Set TH.thNumber = @AppToReqID
From Thing TH
Inner Join FlxTable FT On TH.thFlxID = FT.ftCounter
Where ftTblName = 'AppToReq'
Select @ErrorNum = @ErrorNum + @@Error
Print 'AppToReqID= ' + Convert(Char(15),@AppToReqID)
Print 'Table AppToReq' --For Troubleshooting
--Insert the necessary IDs from the AppBase and ReqBase tables to this link table.
Insert Into AppToReq (arFlxId, arFlxIDap, arFlxIDrb, arUserName)
Values(@AppToReqID, @AppBaseID, @RBID, 'RMSImportProcess')
Select @ErrorNum = @ErrorNum + @@Error
--SAVE TRANSACTION InsertNewEmp
If @ErrorNum <> 0
Begin
ROLLBACK TRANSACTION
Print 'Error: ' + Convert(VarChar(15), @ErrorNum)
--Return @ErrorNum
End
Else
Begin
Commit Transaction
End
End
Thanks,
Chris
February 6, 2007 at 3:40 am
Your second SP still uses a pseudo cursor.
You should really look at writing set based code. To do this one needs to know the DDL (CREATE TABLE with PKs and FKs etc) of the source and destination tables. Temporary tables may needed to generate IDs etc.
February 6, 2007 at 6:34 am
Hi Chris,
You check for the Error count after every Insert or update statement and do a rollback on each check if the count is greater than zero also check the max(rbFlxID) from ReqBase table and see if your thNumber in Thing table is less than that for the filter you are applying to retrieve the thNumber.
Obviously your Insert is failing as you are trying to insert a duplicate key into ReqBase table. I don't won't to comment on the design of your tables as you have already mentioned that they were not properly designed.
Prasad Bhogadi
www.inforaise.com
February 6, 2007 at 6:55 am
Prasad,
Changing that, either using
If @@Error > 1
Or
Set @ErrorNum = @@Error
If @ErrorNum > 1
actually did not help, but did change the behavior slightly.
Out of what should be 13 records, 13 recruits, I got one record in tables 1 and 2. Table 3, got none, due to the PK violation, and table 4, which is a link table between table 1 and table 3, got 2 records.
I'm going to have to analyze this some more to see if I can figure out what's going on, besides the obvious fact that the error checking is not working.
Thanks,
Chris
PS - I believe that if you design a DB for a product, you should have to go through a public review of the design before you are allowed to sell it.
February 6, 2007 at 7:00 am
Ok, Check this SET @ErrorNum = @@ERROR
IF @ErrorNum <>0
BEGIN
ROLLBACK TRANSACTION
END
Prasad Bhogadi
www.inforaise.com
February 6, 2007 at 7:15 am
I see the problem use this syntax...
IF @ErrorNum <>0
GO TO ErrHandler
at the bottom, just write a COMMIT TRANSACTION
On the ErrHandler :
ROLLBACK TRANSACTION
Prasad Bhogadi
www.inforaise.com
February 6, 2007 at 7:17 am
This what you had in mind?
Select @ErrorNum = @@Error
If @ErrorNum <> 0
Begin
ROLLBACK TRANSACTION
Print 'Error: ' + Convert(VarChar(15), @ErrorNum)
--Return @ErrorNum
End
It's only getting worse. Now I get the same error about the PK as before, although the error checking should handle it, and on top of that I get this error too:
Server: Msg 3902, Level 16, State 1, Line 246
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
Despite getting that error, it is still inserting one record in tables 1 and 2, and 11 records into table 4. The entire thing is enclosed in this one transaction, within the While loop.
It should drop out of the inserts for the one recruit and go to the next recruit of there is a failure on any insert for that recruit.
Oh, the PK problem is solved now, as I received word from the analyst that we could eliminate the table join that was causing multiple records from the source DB. This is good, but I am keeping it in there for now, so I can use it to help perfect the error handling aspect of the procedure.
Thanks,
Chris
February 6, 2007 at 7:31 am
No luck there. I get the same behavior from that also.
Thanks,
Chris
February 6, 2007 at 8:14 am
Give this a try
Declare @AppBaseID Int
Declare @AppID Int
Declare @AppEEOID Int
Declare @RBID Int
Declare @AppToReqID Int
Declare @SS VarChar(15) --Social Security Number.
Declare @ErrorNum Int
SET NoCount ON
SET Xact_Abort OFF
SET @SS = 0
WHILE @SS Is NOT NULL
BEGIN
SELECT @SS = Min(REPLACE (P.SS, '-', ''))
FROM RMS.dbo.Submits S
INNER Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
INNER Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
INNER Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
WHERE S.Status = 'Hired'
AND C.CostCenterNum <> '99999'
AND S.Current_Emp <> 1
AND S.Former_Emp <> 1
AND (P.SS Is NOT NULL AND LTrim(P.SS) <> '') --Must not have blank SSN.
AND REPLACE (P.SS, '-', '') Not In(SELECT apSocNum FROM VHR_DataSQL.dbo.AppBase)
AND S.StatusDate > DATEADD (d, -5, GETDATE())
AND REPLACE (P.SS, '-', '') > @SS
SELECT @ErrorNum = 0
BEGIN TRANSACTION
--Get new FlxID for AppBase table.
SELECT @AppBaseID = thNumber + 1
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxId = FT.ftCounter
WHERE ftTblName = 'AppBase'
UPDATE TH
SET TH.thNumber = @AppBaseID
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxId = FT.ftCounter
WHERE ftTblName = 'AppBase'
SET @ErrorNum = @@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
Print 'Table AppBase' --For troubleshooting
Print 'AppBaseID= ' + Convert(Char(15),@AppBaseID) --For troubleshooting
--Insert to AppBase.
Insert Into VHR_DataSQL.dbo.AppBase
(apFlxID, apFirstName, apLastName, apSocNum, apStreet1,
apStreet2, apCity, apState, apZip, apHomePhone, ApEMail,
ApStatus, apCountry, apUserName, apAppID)
SELECT
@AppBaseID, LEFT (S.FirstName, 20), LEFT (S.LastName, 20),
LEFT (REPLACE (P.SS, '-', ''), 9), LEFT (S.Address, 35), LEFT (S.Address2, 35), LEFT (S.City, 35),
LEFT (S.State, 35), LEFT (S.Zip, 10),
LEFT (REPLACE (S.Phone, '-', ''), 14), LEFT (S.Email, 64),
LEFT (J.Type, 30),
'USA', 'RMSImportProcess',
S.Submit_ID
FROM RMS.dbo.Submits S
INNER Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
INNER Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
INNER Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
WHERE REPLACE (P.SS, '-', '') = @SS
Print 'SSN: ' + @SS
SET @ErrorNum =@@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
--Get FlxID for AppEEO table.
SELECT @AppEEOID = thNumber + 1
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxId = FT.ftCounter
WHERE ftTblName = 'AppEEO'
UPDATE TH
SET TH.thNumber = @AppEEOID
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxId = FT.ftCounter
WHERE ftTblName = 'AppEEO'
SET @ErrorNum = @@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
Print 'Table AppEEO' --For Troubleshooting
Print 'AppEEOID= ' + Convert(Char(15),@AppEEOID)
--Insert to the AppEEO table.
Insert Into AppEEO (aoFlxID, aoFlxIDap, aoDateBorn, aoSex, aoEthnic, aoVeteran, aoUserName,
aoDateBeg)
SELECT
@AppEEOID,
@AppBaseID,
Convert(DateTime, P.DOB),
ED.Sex,
LEFT (EP.Profile_Name, 30),
IsNull(ED.MilStatus, 'None'),
'RMSImportProcess',
GETDATE()
FROM RMS.dbo.Submits S
INNER Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
INNER Join RMS.dbo.EEODETAILEDTABLE ED On S.Submit_ID = ED.Submit_ID
INNER Join RMS.dbo.eeoProfiles EP On ED.Profile_ID = EP.Profile_ID
INNER Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
INNER Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
INNER Join VHR_DataSQL.dbo.AppBase AP On REPLACE (P.SS, '-', '') = AP.apSocNum
WHERE REPLACE (P.SS, '-', '') = @SS
SET @ErrorNum = @@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
--Print 'ReqBase ID' --For Troubleshooting
--Get latest FlxID for ReqBase.
SELECT @RBID = thNumber + 1
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxId = FT.ftCounter
WHERE ftTblName = 'ReqBase'
UPDATE TH
SET TH.thNumber = @RBID
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxId = FT.ftCounter
WHERE ftTblName = 'ReqBase'
SET @ErrorNum = @@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
Print 'Table ReqBase' --For Troubleshooting
--Insert to the ReqBase table.
Print 'ReqID= ' + Convert(VarChar(15),@RBID)
Insert Into ReqBase (rbFlxID, rbTitle, rbDateStart, rbDateEnd, rbSalary,
rbNewHireName, rbSupervisor, rbReqID, rbDivision, rbFlxIDjb,
rbSupervisorFlxIDeb, rbContactFlxIDeb, rbContact, rbUserName)
SELECT
@RBID,
LEFT (JL.JobTitle, 60),
Convert(DateTime,P.StartDate) AS StartDate,
Convert(DateTime,P.EndDate) AS EndDate,
Convert(Decimal(18,0), P.Salary),
LEFT (P.Sign_On, 40),
LEFT (M.FirstName + ' '+ M.LastName, 30) As ManagerName,
LEFT (J.REQ, 30),
LEFT (C.CostCenterNum, 30) As UnitNbr,
JB.jbFlxID,
M.[User_ID],
Case IsNumeric(U2.[User_Name])
When 1 Then U2.[User_Name]
Else Null
End as RecruiterID,
LEFT (U1.UserFirstName + ' ' + U1.UserLastName, 30) As Recruiter,
'RMSImportProcess'
FROM RMS.dbo.Submits S
INNER Join RMS.dbo.Placement P On S.Submit_ID = P.Submit_ID
INNER Join RMS.dbo.Jobs J On P.Job_ID = J.Job_ID
INNER Join RMS.dbo.JobLibrary JL On J.JobLibraryID = JL.JobLibraryID
INNER Join RMS.dbo.JobCodes JC On JL.JobCodeID = JC.JobCodeID
INNER Join RMS.dbo.Managers M On P.Man_ID = M.Man_ID
INNER Join RMS.dbo.Users U2 On M.Man_ID = U2.Man_ID
INNER Join RMS.dbo.Users U1 On M.[User_ID] = U1.[User_ID]
INNER Join RMS.dbo.tblBranchInfo BR On M.BranchID = BR.BranchID
INNER Join RMS.dbo.Clients CL On BR.BranchID = CL.BranchID
INNER Join RMS.dbo.CostCenterNum C On J.CostCenterNumID = C.CostCenterNumID
INNER Join VHR_DataSQL.dbo.JobCode JB On JB.jbJobCode = JC.JobCode
INNER Join VHR_DataSQL.dbo.AppBase AP On AP.apSocNum = REPLACE (P.SS, '-', '')
WHERE REPLACE (P.SS, '-', '') = @SS
SET @ErrorNum =@@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
--Print 'AppToReq ID' --For Troubleshooting
--Get latest FlxID for the AppToReq table.
SELECT @AppToReqID = thNumber + 1
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxID = FT.ftCounter
WHERE ftTblName = 'AppToReq'
UPDATE TH
SET TH.thNumber = @AppToReqID
FROM Thing TH
INNER Join FlxTable FT On TH.thFlxID = FT.ftCounter
WHERE ftTblName = 'AppToReq'
SET @ErrorNum = @@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
Print 'AppToReqID= ' + Convert(Char(15),@AppToReqID)
Print 'Table AppToReq' --For Troubleshooting
--Insert the necessary IDs FROM the AppBase AND ReqBase tables to this link table.
Insert Into AppToReq (arFlxId, arFlxIDap, arFlxIDrb, arUserName)
Values(@AppToReqID, @AppBaseID, @RBID, 'RMSImportProcess')
SET @ErrorNum = @@ERROR
IF @ErrorNum <>0
GOTO ErrHandler
COMMIT TRANSACTION
RETURN
ErrHandler:
ROLLBACK
RETURN
END
Prasad Bhogadi
www.inforaise.com
February 6, 2007 at 8:58 am
It works better. I still get the error message from the PK violation though, and it doesn't go on to the next recruit.
Server: Msg 2627, Level 14, State 1, Line 142
Violation of PRIMARY KEY constraint 'PK_ReqBase_RbFlxID'. Cannot insert duplicate key in object 'ReqBase'.
The statement has been terminated.
The good thing here, though, is that no records are inserted into any tables with this procedure.
Thanks,
Chris
February 6, 2007 at 9:18 am
Chris,
To avoid the primary key violation error, you'll have to either eliminate the duplicates before trying to INSERT the data, or by checking for duplicates as part of the INSERT.
In the first method, you could first delete any existing rows in your source data, then insert everything.
Or, add a NOT EXISTS (SELECT * FROM WHERE ...)
to the SELECT statement portion of the INSERT.
For example, for the ReqBase table insert:
...
WHERE REPLACE (P.SS, '-', '') = @SS
AND NOT EXISTS (SELECT * FROM ReqBase WHERE ReqBase.rbFlxID = @RBID)
Viewing 15 posts - 1 through 14 (of 14 total)
You must be logged in to reply to this topic. Login to reply