Как я могу получить фактический номер строки хранимой процедуры из сообщения об ошибке?

112

Когда я использую SQL Server и возникает ошибка, в сообщении об ошибке указывается номер строки, не связанный с номерами строк в хранимой процедуре. Я предполагаю, что разница связана с пробелами и комментариями, но так ли это на самом деле?

Как я могу связать эти два набора номеров строк друг с другом? Если бы кто-нибудь мог дать мне хотя бы указатель в правильном направлении, я был бы очень признателен.

Я использую SQL Server 2005.

чама
источник
1
Думаю, номер строки относится к телу прока. т.е. игнорировать заголовок.
Мартин Смит
Возможно, stackoverflow.com/questions/4550342/… поможет.
Джон Сондерс,
Где заканчивается заголовок? После начала, которое следует за процедурой изменения ... КАК?
chama
В create procмоем тесте казалось, что он начал отсчет с линии. Я полагаю, вы видите что-то другое.
Мартин Смит
1
Описано в моем ответе здесь: stackoverflow.com/questions/2947173/…
gbn

Ответы:

114

IIRC, он начинает подсчет строк с начала пакета, который создал этот процесс. Это означает либо начало сценария, либо последний оператор «GO» перед оператором create / alter proc.

Более простой способ увидеть это - извлечь фактический текст, который SQL Server использовал при создании объекта. Переключите вывод в текстовый режим (CTRL-T с сопоставлением клавиш по умолчанию) и запустите

sp_helptext proc_name

Скопируйте и вставьте результаты в окно скрипта, чтобы получить подсветку синтаксиса и т. Д., И используйте функцию goto line (я думаю, CTRL-G), чтобы перейти к сообщаемой строке ошибки.

Рик
источник
14
Когда я сделал это в режиме Grid-Output, он также застрял в номерах строк
как и
2
@codeulike - Хороший момент, если вы используете вывод сетки, номер строки будет соответствовать номеру строки, поэтому вам не нужно использовать CTRL + G. Моя единственная проблема с выводом Grid заключается в том, что он меняет символы TAB на один SPACE, поэтому вы теряете все форматирование.
Rick
33

По привычке помещаю LINENO 0сразу после BEGINв свои хранимые процедуры. Это сбрасывает номер строки - в данном случае на ноль. Затем просто добавьте номер строки, указанный в сообщении об ошибке, к номеру строки в SSMS, где вы написали, LINENO 0и bingo - у вас есть номер строки с ошибкой, представленный в окне запроса.

Vorlic
источник
4
Почему бы просто не поместить «LineNo X», где X = номер строки, в которую вы помещаете оператор, чтобы он автоматически добавлялся к указанному номеру строки?
LarryBud
8

Если вы используете блок Catch и использовали RAISERROR () для любой проверки кода в блоке Try, то в строке ошибок сообщается, где находится блок Catch, а не где произошла настоящая ошибка. Я использовал это вот так, чтобы прояснить это.

BEGIN CATCH
  DECLARE @ErrorMessage NVARCHAR(4000);
  DECLARE @ErrorSeverity INT;
  DECLARE @ErrorState INT;

  SELECT 
     @ErrorMessage = ERROR_MESSAGE() + ' occurred at Line_Number: ' + CAST(ERROR_LINE() AS VARCHAR(50)),
     @ErrorSeverity = ERROR_SEVERITY(),
     @ErrorState = ERROR_STATE();

  RAISERROR (@ErrorMessage, -- Message text.
     @ErrorSeverity, -- Severity.
     @ErrorState -- State.
  );

END CATCH
Эдвард
источник
6

На самом деле это Error_number()работает очень хорошо.

Эта функция начинает отсчет с последнего оператора GO (Batch Separator), поэтому, если вы не использовали пробелы Go, но он по-прежнему показывает неправильный номер строки, добавьте к нему 7, как в хранимой процедуре в строке номер 7 разделитель пакетов используется автоматически. Поэтому, если вы выберете Cast (Error_Number () + 7 as Int) в качестве [Error_Number] - вы получите желаемый ответ.

user2294834
источник
1
if you have not used any Go spaces and it is still showing a wrong line number - then add 7 to it, as in stored procedure in line number 7 the batch separator is used automatically.- что это должно было значить?
underscore_d
4

В TSQL / хранимых процедурах

Вы можете получить такую ​​ошибку, как:

Msg 206, уровень 16, состояние 2, процедура myproc, строка 177 [Batch Start Line 7]

Это означает, что ошибка находится в строке 177 пакета. Не 177 в SQL. Вы должны увидеть, с какого номера строки начинается ваш пакет, в моем случае [7], а затем вы добавляете это значение к номеру строки, чтобы определить, какой оператор неверен.

Jasttim
источник
2

вы можете использовать это

CAST(ERROR_LINE() AS VARCHAR(50))

и если вы хотите создать таблицу журнала ошибок, вы можете использовать это:

INSERT INTO dbo.tbname( Source, Message) VALUES ( ERROR_PROCEDURE(), '[ ERROR_SEVERITY : ' + CAST(ERROR_SEVERITY() AS VARCHAR(50)) + ' ] ' + '[ ERROR_STATE : ' + CAST(ERROR_STATE() AS VARCHAR(50)) + ' ] ' + '[ ERROR_PROCEDURE : ' + CAST(ERROR_PROCEDURE() AS VARCHAR(50)) + ' ] ' + '[ ERROR_NUMBER : ' + CAST(ERROR_NUMBER() AS VARCHAR(50)) + ' ] ' +  '[ ERROR_LINE : ' + CAST(ERROR_LINE() AS VARCHAR(50)) + ' ] ' + ERROR_MESSAGE())
HAJJAJ
источник
4
Обратите внимание, что ERROR_LINE () доступна только в части CATCH TRY / CATCH внутри хранимой процедуры. Номер строки, который он сообщает, совпадает с номером строки, который возвращает SQL Server, если вы не поймаете ошибку. Так что, хотя это может быть полезно, это не помогает решить этот вопрос.
Рик
1

Длинный ответ: номер строки отсчитывается от CREATE PROCEDUREоператора, плюс любые пустые строки или строки комментариев, которые могли быть над ним, когда вы действительно запускали CREATEоператор, но не считая никаких строк перед GOоператором ...

Я обнаружил, что намного проще сделать сохраненный процесс, чтобы поиграть с ним, чтобы подтвердить:

GO

-- =============================================
-- Author:          <Author,,Name>
-- Create date: <Create Date,,>
-- Description:     <Description,,>
-- =============================================
CREATE PROCEDURE ErrorTesting
       -- Add the parameters for the stored procedure here
AS
BEGIN
       -- SET NOCOUNT ON added to prevent extra result sets from
       -- interfering with SELECT statements.
       SET NOCOUNT ON;

       -- Insert statements for procedure here
       SELECT 1/0

END
GO

После того, как вы создали его, вы можете переключиться на него ALTER PROCEDUREи добавить несколько пустых строк над комментариями, а также над и под первымGO оператором, чтобы увидеть эффект.

Одна очень странная вещь, которую я заметил, заключалась в том, что мне приходилось запускать EXEC ErrorTestingв новом окне запроса вместо того, чтобы выделять его в нижней части того же окна и запускать… Когда я это делал, номера строк продолжали расти! Не знаю, почему это произошло ...

Энди Раддац
источник
1

вы можете получить сообщение об ошибке и строку ошибки в блоке catch следующим образом:

'Ms Sql Server Error: - ' + ERROR_MESSAGE() + ' - Error occured at: ' + CONVERT(VARCHAR(20),  ERROR_LINE())
Бадипармаги
источник