Frage

Ich habe ein Skript geschrieben, das mehrere tausend Zeilen lang ist, mit denen ich einige gespeicherte Prozeduren dynamisch generiere.

Ich möchte auf das Skript verweisen, das die gespeicherten Prozeduren in den Kommentaren in den gespeicherten Prozeduren generiert hat, und möchte in der Lage sein, auf die Zeile in der Skriptdatei zu verweisen, indem die Zeilennummer der Skriptdatei in die Kommentare in der gespeicherten Prozedur eingefügt wird Datei.

Also, wenn @@ line_number die gewünschte Zeilennummer im Code bellow angegeben hat, sollte @@ line_number 5 sein

1| declare @job varchar(max)
2| SET @job = '/* this is generated dynamicly by _______  */'
3| SET @job = @job + 'SELECT *' + CHAR(10)
4| SET @job = @job + 'FROM ' + @Table_Name + CHAR(10)
5| SET @job = @job + '/* ' + @@line_number + ' */'
War es hilfreich?

Lösung

Sie können Try / Fang mit einem erzwungenen Fehler verwenden, da der Catch -Block die Zeilennummer zurückgeben kann, die der Fehler über die Funktion error_line () aufgetreten ist. Das vollständige Konstrukt, das zur Lesbarkeit formatiert ist, lautet:

BEGIN TRY
    ;THROW 50000, 'Line#', 1 -- all 3 values are arbitrary, but required
END TRY
BEGIN CATCH
    SET @LineNumber = ERROR_LINE()
END CATCH

Um die Variable @linenumber so zu erhalten, dass sie sich mit der Zeilennummer, auf die sie eingestellt ist, können Sie dieses Konstrukt wie folgt auf eine einzelne Zeile reduzieren:

BEGIN TRY;THROW 50000,'',1;END TRY BEGIN CATCH;SET @Line=ERROR_LINE();END CATCH

Hier ist ein vollständiges Beispiel dafür:

SET ANSI_NULLS ON
SET NOCOUNT ON
GO
-- Line #1 (of current batch, not of the entire script if GOs are used)

DECLARE @CRLF NCHAR(2) = NCHAR(13) + NCHAR(10),
        @SQL1 NVARCHAR(MAX) = '',
        @SQL2 NVARCHAR(MAX) = '', -- Line #5
        @Line INT = -1 -- default to an invalid line #

SET @SQL1 += N'/********************' + @CRLF
SET @SQL1 += N' *' + @CRLF
SET @SQL1 += N' * Test Auto-' + @CRLF -- Line #10
SET @SQL1 += N' * Generated Proc 1' + @CRLF
BEGIN TRY;THROW 50000,'',1;END TRY BEGIN CATCH;SET @Line=ERROR_LINE();END CATCH
SET @SQL1 += N' * Line #:' + CONVERT(NVARCHAR(10), @Line) + @CRLF
SET @SQL1 += N' *' + @CRLF
SET @SQL1 += N' ********************/' + @CRLF -- Line #15

-- more code here

SET @SQL2 += N'/********************' + @CRLF
SET @SQL2 += N' *' + @CRLF -- Line #20
SET @SQL2 += N' * Test Auto-' + @CRLF
SET @SQL2 += N' * Generated Proc 2' + @CRLF
BEGIN TRY;THROW 50000,'',1;END TRY BEGIN CATCH;SET @Line=ERROR_LINE();END CATCH
SET @SQL2 += N' * Line #:' + CONVERT(NVARCHAR(10), @Line) + @CRLF
SET @SQL2 += N' *' + @CRLF -- Line #25
SET @SQL2 += N' ********************/' + @CRLF

PRINT @SQL1
PRINT @SQL2
GO

Die für Proc 1 und Proc 2 zurückgegebenen Liniennummern betragen 12 bzw. 23, was für beide korrekt ist.

Bitte beachten Sie, dass der Wurfbefehl in SQL Server 2012 gestartet wurde. Wenn Sie SQL Server 2005, 2008 oder 2008 R2 verwenden, müssen Sie Raiserror () -Funktion anstelle von Wurf verwenden.

Andere Tipps

ich habe mich verändert Solomonrutzkys Antwort Ein wenig zu bekommen ist die Arbeit in SQL Server -Versionen vor 2012 zu arbeiten:

DECLARE @Line INT
SET @Line = 0 BEGIN TRY RAISERROR ('Line#', 11, 1)WITH NOWAIT   END TRY BEGIN CATCH SET @Line=ERROR_LINE() END CATCH

PRINT('/* testing ... I messed up somewhere near line: ' + CONVERT(varchar(10), ISNULL(@Line, 0)) + ' */')

Ich habe keine integrierte Funktion gefunden, um die aktuelle Zeilennummer zurückzugeben, daher habe ich begonnen, eine Funktion zu erstellen, um die Zeilennummer für mich zu finden.

Wenn ich den Text der aktuellen laufenden Abfrage oben erhalte und eine Variable deklariere und dann den Funktionsaufruf und den @LineCounter -Inkrementcode kopieren und überschreiten kann, kann ich die aktuelle Zeilennummer abrufen.

    DECLARE @var1 NVARCHAR(MAX) 
    SELECT @var1 = sqltext.TEXT
    FROM sys.dm_exec_requests req
    CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext
    WHERE req.session_id = @@SPID
    DECLARE @LineCounter int
    SET @LineCounter = 0
    DECLARE @Current_Line_Number int
    SET @Current_Line_Number = 0
SET @LineCounter = @LineCounter + 1
SELECT @Current_Line_Number = [MSMS].[dbo].[ReturnLineNumber] (@var1, @LineCounter)
PRINT @Current_Line_Number

Dies ist die Funktion

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      James J
-- Create date: 11/11/2013
-- Description: Function to return the line number for 
-- where the query was called from when passed the query 
-- an the count of the times it has already been used.
-- =============================================
ALTER FUNCTION ReturnLineNumber 
(
    @CurrentQuery nvarchar(max), 
    @Count  int
)
RETURNS int
AS
BEGIN
    DECLARE @var1 NVARCHAR(MAX) 
    DECLARE @functionName nvarchar(30)
    SET @functionName = 'ReturnLineNumber'
    SET @var1 = @CurrentQuery

    DECLARE @LineCount int
    SET @LineCount = 0

    IF (CHARINDEX(CHAR(13), @var1) > 0)
    BEGIN
        DECLARE @queryString nvarchar(max)
        SET @queryString = @var1
        DECLARE @LineIndex int
        SET @LineIndex = 1
        DECLARE @LineLength int
        DECLARE @linestring nvarchar(max)
        DECLARE @functioncount int
        SET @functioncount = 0
        WHILE (@LineIndex > 0)
        BEGIN
            SET @LineIndex = CHARINDEX(CHAR(13), @queryString)
            SET @LineLength = LEN(@queryString) - CHARINDEX(CHAR(13), @queryString)
            SET @linestring = SUBSTRING(@queryString, 0, @LineIndex + 1)
            SET @queryString = SUBSTRING(@queryString, @LineIndex + 1, @LineLength)
            SET @LineCount = @LineCount + 1
            IF (CHARINDEX(@functionName, @linestring) > 0)
            BEGIN
                SET @functioncount = @functioncount + 1
                IF (@functioncount = @Count)
                BEGIN
                    RETURN @LineCount
                END
            END
        END
    END
    RETURN 0
END
GO

Dies ist keine gute Möglichkeit, die Zeilennummer zu erhalten, und ich sollte wahrscheinlich noch einige weitere Schecks hinzufügen, um sicherzustellen, dass ich keine Funktionsanrufe kommentiert habe, aber dies ist die am nächsten gelegene, die ich momentan habe.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top