Sql server sql错误处理和输出

Sql server sql错误处理和输出,sql-server,stored-procedures,error-handling,Sql Server,Stored Procedures,Error Handling,我有下面的代码,它遍历每一行,并为行中的每个值运行存储的过程。某些值失败,代码继续执行下一个值,直到为整个表运行SP为止 我需要知道的是,如何生成一个列表,列出它尝试和失败的所有行。我不希望它在失败时停止,因为它应该完成,但它应该让我知道它不适用于的rowsID,这样我就可以针对失败的行再次运行它 DECLARE @SP VARCHAR(50) DECLARE @ROWID INT DECLARE @MAXROW INT DECLARE @HEADOFFICECL

我有下面的代码,它遍历每一行,并为行中的每个值运行存储的过程。某些值失败,代码继续执行下一个值,直到为整个表运行SP为止

我需要知道的是,如何生成一个列表,列出它尝试和失败的所有行。我不希望它在失败时停止,因为它应该完成,但它应该让我知道它不适用于的rowsID,这样我就可以针对失败的行再次运行它

    DECLARE @SP VARCHAR(50)
    DECLARE @ROWID INT
    DECLARE @MAXROW INT
    DECLARE @HEADOFFICECLIENTINVOICEID VARCHAR(50)
    DECLARE @OUTLETID VARCHAR(50)
    DECLARE @COMPANYINFOID VARCHAR(50)
    DECLARE @YEARID VARCHAR(50)
    DECLARE @AREAID VARCHAR(50)
    DECLARE @REPORTSTYLE VARCHAR(50)
    DECLARE @STARTDATE VARCHAR(50)
    DECLARE @ENDDATE VARCHAR(50)
    DECLARE @SQL VARCHAR(1000)

    SET @SP = 'FINANCE_BUDGETING_AGAINST_ACTUAL_REPORT'
    SET @ROWID = 1

    SELECT @MAXROW = MAX(ROWID)
    FROM #AKTEMP

    WHILE @ROWID <= @MAXROW
    BEGIN
        SELECT @HEADOFFICECLIENTINVOICEID = HEADOFFICECLIENTINVOICESID
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SELECT @OUTLETID = OUTLETID
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SELECT @COMPANYINFOID = COMPANYINFOID
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SELECT @YEARID = YEARID
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SELECT @AREAID = AREAID
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SELECT @REPORTSTYLE = REPORTSTYLE
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SELECT @STARTDATE = CONVERT(VARCHAR(11), REPORTDATEFROM, 106)
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SELECT @ENDDATE = CONVERT(VARCHAR(11), REPORTDATETO, 106)
        FROM #AKTEMP
        WHERE ROWID = @ROWID

        SET @SQL = @SP + ' @HEADOFFICECLIENTINVOICEID = ' + @HEADOFFICECLIENTINVOICEID +
                        ', @OUTLETID = ' + @OUTLETID + 
                        ', @COMPANYINFOID = ' + @COMPANYINFOID + 
                        ', @YEARID = ' + @YEARID + 
                        ', @AREAID = ' + @AREAID + 
                        ', @REPORTSTYLE = ' + @REPORTSTYLE + 
                        ', @STARTDATE = ''' + @STARTDATE + '''' + 
                        ', @ENDDATE = ''' + @ENDDATE + ''''

        PRINT @SQL
        PRINT @ROWID

        EXEC (@SQL)

        SET @ROWID = @ROWID + 1
    END

我使用Try-Catch错误处理进行处理。若出现错误,它将捕获表变量@TAB中的rowid

注意:我没有检查它,因为您的案例没有可用的模式

    DECLARE @SP VARCHAR(50)
    DECLARE @ROWID INT
    DECLARE @MAXROW INT
    DECLARE @HEADOFFICECLIENTINVOICEID VARCHAR(50)
    DECLARE @OUTLETID VARCHAR(50)
    DECLARE @COMPANYINFOID VARCHAR(50)
    DECLARE @YEARID VARCHAR(50)
    DECLARE @AREAID VARCHAR(50)
    DECLARE @REPORTSTYLE VARCHAR(50)
    DECLARE @STARTDATE VARCHAR(50)
    DECLARE @ENDDATE VARCHAR(50)
    DECLARE @SQL VARCHAR(1000)

    SET @SP = 'FINANCE_BUDGETING_AGAINST_ACTUAL_REPORT'
    SET @ROWID = 1

    SELECT @MAXROW = MAX(ROWID)
    FROM #AKTEMP

    DECLARE @TAB TABLE (
        SNO INT IDENTITY
        ,ROWID INT
        )

    WHILE @ROWID <= @MAXROW
    BEGIN
        BEGIN TRY
            SELECT @HEADOFFICECLIENTINVOICEID = HEADOFFICECLIENTINVOICESID
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SELECT @OUTLETID = OUTLETID
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SELECT @COMPANYINFOID = COMPANYINFOID
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SELECT @YEARID = YEARID
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SELECT @AREAID = AREAID
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SELECT @REPORTSTYLE = REPORTSTYLE
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SELECT @STARTDATE = CONVERT(VARCHAR(11), REPORTDATEFROM, 106)
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SELECT @ENDDATE = CONVERT(VARCHAR(11), REPORTDATETO, 106)
            FROM #AKTEMP
            WHERE ROWID = @ROWID

            SET @SQL = @SP + ' @HEADOFFICECLIENTINVOICEID = ' + @HEADOFFICECLIENTINVOICEID + ', @OUTLETID = ' + @OUTLETID + ', @COMPANYINFOID = ' + @COMPANYINFOID + ', @YEARID = ' + @YEARID + ', @AREAID = ' + @AREAID + ', @REPORTSTYLE = ' + @REPORTSTYLE + ', @STARTDATE = ''' + @STARTDATE + '''' + ', @ENDDATE = ''' + @ENDDATE + ''''

            PRINT @SQL
            PRINT @ROWID

            EXEC (@SQL) END
            SET @ROWID = @ROWID + 1
        END TRY

        BEGIN CATCH
            INSERT INTO @TAB
            SELECT @ROWID

            SET @ROWID = @ROWID + 1
        END CATCH
    END

    SELECT * FROM @TAB

为了在不影响整个过程的情况下处理SQL错误,可以在SQL Server上使用classic及其语法

下面是我如何修改您的SQL代码的

Declare @SP varchar(50)
Declare @RowID int
Declare @MaxRow int
Declare @HeadofficeclientinvoiceID varchar(50)
Declare @Outletid varchar(50)
Declare @CompanyInfoID varchar(50)
Declare @YearID varchar(50)
Declare @AreaID varchar(50)
Declare @ReportStyle varchar(50)
Declare @Startdate varchar(50)
Declare @Enddate varchar(50)
Declare @sql varchar(1000)


Set @SP = 'Finance_Budgeting_Against_Actual_Report'
Set @RowID = 1
Select @MaxRow = MAX(rowid) from #AKTemp

While @RowID <= @MaxRow
Begin

Select 
    @HeadofficeclientinvoiceID = HeadOfficeClientInvoicesID,
    @Outletid = Outletid,
    @CompanyInfoID = CompanyInfoID,
    @YearID = YearID,   
    @AreaID = AreaID, 
    @ReportStyle = ReportStyle,
    @Startdate = CONVERT(VARCHAR(11),ReportDateFrom, 106),
    @Enddate = CONVERT(VARCHAR(11),ReportDateTo, 106)
from #AKTemp where RowID = @RowID

Set @sql = @SP
+' @HeadofficeclientinvoiceID = '+ @HeadofficeclientinvoiceID 
+ ', @Outletid = ' + @Outletid 
+ ', @CompanyInfoID = ' + @CompanyInfoID
+ ', @YearID = ' + @YearID
+ ', @AreaID = ' + @AreaID
+ ', @ReportStyle = ' + @ReportStyle
+ ', @Startdate = ''' + @Startdate + '''' 
+ ', @Enddate = ''' + @Enddate + ''''

Set @sql = @SP

BEGIN TRY
    Exec(@sql)
END TRY
BEGIN CATCH
    print 'Error:'
    Print @Sql
    Print @RowID 
END CATCH;


    Set @RowID = @RowID + 1
End
请注意,我使用一条SQL select语句从临时表行中选择参数。您可以修改代码以获得更好的性能

第二,请注意SQL Try…Catch块。
您可以根据需要修改CATCH块,以报告发生错误的行,而不是使用WHILE命令,另一个选项是使用SQL游标,它将迭代游标的所有行。有关基本信息,请参阅给定参考资料

请检查为您的案例实现的以下SQL游标代码。您将看到它与您的WHILE循环非常相似

Declare @SP varchar(50)
Declare @RowID int
Declare @MaxRow int
Declare @HeadofficeclientinvoiceID varchar(50)
Declare @Outletid varchar(50)
Declare @CompanyInfoID varchar(50)
Declare @YearID varchar(50)
Declare @AreaID varchar(50)
Declare @ReportStyle varchar(50)
Declare @Startdate varchar(50)
Declare @Enddate varchar(50)
Declare @sql varchar(1000)
Set @SP = 'Finance_Budgeting_Against_Actual_Report'


DECLARE mycursor CURSOR FAST_FORWARD FOR SELECT RowID from #AKTemp
OPEN mycursor
FETCH NEXT FROM mycursor INTO @RowID

WHILE @@FETCH_STATUS = 0
BEGIN
-------------------------------------------
Select 
    @HeadofficeclientinvoiceID = HeadOfficeClientInvoicesID,
    @Outletid = Outletid
    @CompanyInfoID = CompanyInfoID,
    @YearID = YearID,   
    @AreaID = AreaID, 
    @ReportStyle = ReportStyle,
    @Startdate = CONVERT(VARCHAR(11),ReportDateFrom, 106),
    @Enddate = CONVERT(VARCHAR(11),ReportDateTo, 106)
from #AKTemp
where RowID = @RowID

Set @sql = @SP
+' @HeadofficeclientinvoiceID = '+ @HeadofficeclientinvoiceID 
+ ', @Outletid = ' + @Outletid 
+ ', @CompanyInfoID = ' + @CompanyInfoID
+ ', @YearID = ' + @YearID
+ ', @AreaID = ' + @AreaID
+ ', @ReportStyle = ' + @ReportStyle
+ ', @Startdate = ''' + @Startdate + '''' 
+ ', @Enddate = ''' + @Enddate + ''''

BEGIN TRY
    Exec(@sql)
END TRY
BEGIN CATCH
    print 'Error:'
    Print @Sql
    Print @RowID 
END CATCH;
-------------------------------------------
 FETCH NEXT FROM mycursor INTO @RowID
END

CLOSE mycursor
DEALLOCATE mycursor

看起来不需要动态部件:

SET NOCOUNT ON

DECLARE
  @ROWID INT,
  @MAXROW INT,
  @HEADOFFICECLIENTINVOICEID VARCHAR(50),
  @OUTLETID VARCHAR(50),
  @COMPANYINFOID VARCHAR(50),
  @YEARID VARCHAR(50),
  @AREAID VARCHAR(50),
  @REPORTSTYLE VARCHAR(50),
  @STARTDATE VARCHAR(50),
  @ENDDATE VARCHAR(50),
  @SQL VARCHAR(1000),
  @crRows cursor

SET @crRows = CURSOR FAST_FORWARD
SELECT t.HeadofficeclientinvoiceID, t.Outletid, t.CompanyInfoID, 
  t.YearID, t.AreaID, t.ReportStyle, t.Startdate, t.Enddate
FROM #AKTEMP t
ORDER BY t.ROWID

OPEN @crRows

FETCH NEXT FROM @crRows
INTO @HeadofficeclientinvoiceID, @Outletid, @CompanyInfoID, 
  @YearID, @AreaID, @ReportStyle, @Startdate, @Enddate

WHILE @@FETCH_STATUS = 0
BEGIN TRY

  EXEC dbo.FINANCE_BUDGETING_AGAINST_ACTUAL_REPORT
    @HeadofficeclientinvoiceID = @HeadofficeclientinvoiceID,
    @Outletid       = @Outletid,
    @CompanyInfoID  = @CompanyInfoID,
    @YearID         = @YearID,
    @AreaID         = @AreaID,
    @ReportStyle    = @ReportStyle,
    @Startdate      = @Startdate
    @Enddate        = @Enddate

  FETCH NEXT FROM @crRows
  INTO @HeadofficeclientinvoiceID, @Outletid, @CompanyInfoID, 
    @YearID, @AreaID, @ReportStyle, @Startdate, @Enddate
END TRY
BEGIN CATCH
  /* CATCH PART FROM @Shakeer's answer */
END

CLOSE @crRows
DEALLOCATE crRows

也许您需要将@RowID附加到游标获取部分,然后选择

为什么不将失败行的ID放在一个表中呢?您好,是的,这样可以。但是我不知道我会键入什么代码来识别失败的ID和成功的ID。您可以使用一个select语句设置所有值,例如:select@OutletID=OuletID、@AreaID=AreaID、@。。。在AKTemp中,rowid=@rowidyou甚至可以用一个select来构建整个脚本:select@sql+='@OutletID='+castOutletID as varchar10+',“+…谢谢,这让查询变得更好