我有一个我编写的脚本,它在特定行上给出了3930错误。这是一个简单的更新语句,当我在脚本中运行它时它会失败,但是如果我从脚本中打印变量并手动运行它就行了。有人知道我如何追踪这个错误吗?
该行在游标中执行,并在此循环之前正确运行数百次。如果我让它处理所有记录或更新我的光标查询以仅选择这个记录,我会收到错误。
完整的错误消息是:
Msg 3930,Level 16,State 1,Line 160
当前事务无法提交,也无法支持写入日志文件的操作。回滚交易。
违规行是:
UPDATE [DBName].[dbo].[TableName]
SET [XXX] = @XXX, [DateEdited] = GETDATE(), [EditedBy] = 'MyUser'
WHERE [YYY] = @YYY
编辑:
我清理了查询,以便我可以在这里发布;见下文。有几点需要注意。
1)对于承包商“ABCDEF”,[FactoryDB]中只有一条记录。[dbo]。[AuditInformation]因此该记录不需要光标B.我尝试删除光标并保留所有包含的代码,但修复了错误
2)删除解析年龄的try-catch块也会修复错误,即使它没有被任何剩余代码使用。 FYI代码执行错误并执行catch块。
--TABLE TO HOLD ERROR MESSAGES
declare @errors TABLE (FormId int, FactoryContractorCode nvarchar(50), FactoryId nvarchar(50), ErrorMessage nvarchar(1000) )
--DECLARE VARIABLES
DECLARE @factoryCode nvarchar(50)
DECLARE @factoryId nvarchar(50)
DECLARE @formId int
DECLARE @auditDate DateTime
DECLARE @totalEmployees int
DECLARE @ageRange nvarchar(50)
DECLARE @ageAverage int
DECLARE @percentageFemale int
DECLARE @percentageMale int
DECLARE @rowIdToUpdate nvarchar(50)
DECLARE @tempFormId int
DECLARE @tempDateString nvarchar(50)
DECLARE @tempAuditDate DateTime
--CURSOR TO LOOP THROUGH ALL FACTORY CODES
DECLARE a CURSOR FOR
SELECT DISTINCT [FactoryCode] FROM [FactoryDB].[dbo].[AuditInformation] WHERE [FactoryCode] = 'ABCDEF'
OPEN a
FETCH a into @factoryCode
WHILE(@@FETCH_STATUS = 0)
BEGIN
BEGIN TRANSACTION
--RESET VARIABLES TO NULL
SET @totalEmployees = NULL
SET @ageRange = NULL
SET @formId = NULL
SET @rowIdToUpdate = NULL
SET @tempAuditDate = NULL
SET @auditDate = NULL
SET @ageAverage = NULL
SET @percentageFemale = NULL
SET @percentageMale = NULL
SET @tempFormId = NULL
SET @tempDateString = NULL
SET @factoryId = NULL
SELECT @factoryId=[ContractorID] FROM [DataDB].[dbo].[ContractorIdentifier] WHERE [ContractorCode] = @factoryCode
--FIND THE FORM ID WITH THE MOST RECENT DATE
DECLARE b CURSOR FOR
SELECT [FormId],[StartDate] FROM [FactoryDB].[dbo].[AuditInformation] WHERE [FactoryCode] = @factoryCode AND NOT [StartDate] IS NULL
OPEN b
FETCH b into @tempFormId, @tempDateString
WHILE(@@FETCH_STATUS = 0)
BEGIN
--PARSE THE FORM DATE
BEGIN TRY
SET @tempAuditDate = CAST(@tempDateString AS DateTime)
END TRY
BEGIN CATCH
INSERT INTO @errors ([FormId],[FactoryContractorCode],[FactoryId],[ErrorMessage]) VALUES (@tempFormId, @factoryCode, @factoryId, 'Unable to parse date value of: '''+@tempDateString+'''')
END CATCH
--FIRST TIME
IF (@auditDate IS NULL)
BEGIN
SET @auditDate = @tempAuditDate
SET @formId = @tempFormId
END
--UPDATE IF THE NEW DATE IS MORE RECENT THAN THE PREVIOUS ONE
IF(@tempAuditDate > @auditDate)
BEGIN
SET @auditDate = @tempAuditDate
SET @formId = @tempFormId
END
FETCH b into @tempFormId, @tempDateString
END
CLOSE b
DEALLOCATE b
--IF A FORM WAS FOUND WITH A PARSABLE DATE
IF (NOT @formId IS NULL)
BEGIN
--GET AUDIT INFORMATION
SELECT TOP 1
@totalEmployees = m.[TotarEmployees]
,@ageRange = m.[EmployeeAgeRange]
FROM [FactoryDB].[dbo].[AuditInformation] g
INNER JOIN [FactoryDB].[dbo].[AuditData] m on g._form_id = m._form_id
WHERE g.[_form_id] = @formId
--PARSE THE AVERAGE AGE FROM THE VARCHAR COLUMN
BEGIN TRY
DECLARE @low int
DECLARE @high int
SET @low = CAST(LTRIM(RTRIM(SUBSTRING(@ageRange,0,CHARINDEX('-',@ageRange)))) AS int)
SET @high = CAST(LTRIM(RTRIM(SUBSTRING(@ageRange,CHARINDEX('-',@ageRange)+1,LEN(@ageRange)))) AS int)
SET @ageAverage = ROUND((@low+@high)/2, 0)
END TRY
BEGIN CATCH
INSERT INTO @errors ([FormId],[FactoryContractorCode],[FactoryId],[ErrorMessage]) VALUES (@formId, @factoryCode, @factoryId, 'Unable to parse age value of: '''+@ageRange+'''')
END CATCH
END
--UPDATE THE FACTORY VIEW TABLE
SELECT TOP 1 @rowIdToUpdate = [Id] FROM [DataDB].[dbo].[DataTable] WHERE [ContractorID] = @factoryId AND [DateEdited] < @auditDate ORDER BY [DateEdited] DESC
IF (NOT @rowIdToUpdate IS NULL)
BEGIN
IF(NOT @totalEmployees IS NULL)
UPDATE [DataDB].[dbo].[EmployeeStats] SET [TotalEmployees] = @totalEmployees, [DateEdited] = GETDATE(), [EditedBy] = 'LstAD' WHERE [RowIDs] = @rowIdToUpdate
ELSE
INSERT INTO @errors ([FormId],[FactoryContractorCode],[FactoryId],[ErrorMessage]) VALUES (@formId, @factoryCode, @factoryId, 'Did not update Total Employees. Value was null or unable to be calculated.')
END
ROLLBACK
FETCH a into @factoryCode
END
CLOSE a
DEALLOCATE a
--DO SOMETHING WITH THE ERRORS TABLE VARIABLE
SELECT * FROM @errors
答案 0 :(得分:3)
事实证明,即使它在Try / Catch块中,错误也会阻止事务被提交。我没有意识到这一点。我重新编写了“ - 从VARCHAR COLUMN开始平均年龄”代码,在尝试进行数学运算并修复问题之前使用ISNUMERIC作为检查。感谢帮助评论者。否则,我不会想到它。