رقم خط طباعة SQL في التعليق على الإجراء المخزن التي تم إنشاؤها ديناميكيًا؟

StackOverflow https://stackoverflow.com/questions/19850270

سؤال

لقد كتبت برنامج نصي يبلغ طوله عدة آلاف من الخطوط التي أستخدمها لإنشاء بعض الإجراءات المخزنة ديناميكيًا.

أرغب في الإشارة إلى البرنامج النصي الذي أنشأ الإجراءات المخزنة في التعليقات في الإجراءات المخزنة ، وأود أن أكون قادرًا على الرجوع إلى السطر في ملف البرنامج النصي عن طريق إدخال رقم سطر ملف البرنامج النصي في التعليقات في الإجراء المخزن ملف.

على سبيل المثال ، إذا أعطى line_number رقم السطر الذي أريده في الرمز ، يجب أن يكون line_number 5

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 + ' */'
هل كانت مفيدة؟

المحلول

يمكنك استخدام Try / Catch مع وجود خطأ قسري حيث يمكن أن تقوم كتلة Catch بإرجاع رقم السطر الذي حدث فيه الخطأ عبر وظيفة Error_line (). البناء الكامل ، المنسق لقدرة على القراءة ، هو:

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

الآن ، للحصول على متغير @linenumber للملء برقم السطر الذي يتم تعيينه عليه ، يمكنك تقليل هذا البناء إلى سطر واحد على النحو التالي:

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

فيما يلي مثال كامل على العمل:

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

أرقام الخط التي يتم إرجاعها لـ Proc 1 و Proc 2 هي 12 و 23 على التوالي ، وهو أمر صحيح لكليهما.

يرجى ملاحظة أن أمر الرمي الذي بدأ في SQL Server 2012. إذا كنت تستخدم SQL Server 2005 أو 2008 أو 2008 R2 ، فأنت بحاجة إلى استخدام وظيفة Raiserror () بدلاً من الرمي.

نصائح أخرى

لقد تغيرت إجابة سليمونروتزكي بعض الشيء للحصول عليه هو العمل في إصدارات SQL Server قبل عام 2012:

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)) + ' */')

لم أجد وظيفة مدمجة لإرجاع رقم السطر الحالي ، لذا بدأت في عمل وظيفة للعثور على رقم السطر بالنسبة لي.

إذا حصلت على نص استعلام التشغيل الحالي في الجزء العلوي وأعلن بعض المتغيرات ، ثم نسخ وتجاوز استدعاء الوظيفة ورمز زيادة @Linecounter ، يمكنني الحصول على رقم السطر الحالي.

    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

هذه هي الوظيفة

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

هذه ليست طريقة رائعة للحصول على رقم السطر ، وربما يجب أن أضيف المزيد من الشيكات للتأكد من عدم تعليق مكالمات الوظائف ، لكن هذا هو الأقرب الذي حصلت عليه في الوقت الحالي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top