Làm cách nào để lấy số dòng thủ tục được lưu trữ thực tế từ một thông báo lỗi?


110

Khi tôi sử dụng SQL Server và xảy ra lỗi, thông báo lỗi cung cấp số dòng không có mối tương quan với số dòng trong quy trình được lưu trữ. Tôi giả định rằng sự khác biệt là do khoảng trắng và các nhận xét, nhưng thực tế có phải vậy không?

Làm cách nào để tôi có thể liên hệ hai bộ số dòng này với nhau? Nếu ai đó có thể cho tôi ít nhất một chỉ dẫn đi đúng hướng, tôi thực sự rất cảm kích.

Tôi đang sử dụng máy chủ SQL 2005.


1
Tôi nghĩ rằng số dòng liên quan đến phần thân của proc. tức là bỏ qua tiêu đề.
Martin Smith


Tiêu đề kết thúc ở đâu? Sau khi bắt đầu theo thủ tục thay đổi ... AS?
chama

Nó dường như bắt đầu đếm từ create procdòng trong bài kiểm tra của tôi. Tôi cho rằng bạn đang nhìn thấy điều gì đó khác biệt.
Martin Smith

1
Được mô tả trong câu trả lời của tôi tại đây: stackoverflow.com/questions/2947173/…
gbn

Câu trả lời:


113

IIRC, nó bắt đầu đếm các dòng từ đầu lô đã tạo ra proc đó. Điều đó có nghĩa là bắt đầu tập lệnh, hoặc câu lệnh "GO" cuối cùng trước câu lệnh tạo / thay đổi proc.

Một cách dễ dàng hơn để xem điều đó là kéo văn bản thực mà SQL Server đã sử dụng khi tạo đối tượng. Chuyển đầu ra của bạn sang chế độ văn bản (CTRL-T với ánh xạ phím mặc định) và chạy

sp_helptext proc_name

Sao chép, dán kết quả vào cửa sổ tập lệnh để đánh dấu cú pháp, v.v. và sử dụng hàm goto line (tôi nghĩ là CTRL-G) để chuyển đến dòng báo cáo lỗi.


14
Khi tôi đã làm điều này trong chế độ Grid-Output, nó bị mắc kẹt số dòng trên quá
codeulike

2
@codeulike - Điểm tốt, nếu bạn sử dụng Grid output, số hàng sẽ khớp với số dòng, vì vậy bạn không cần sử dụng CTRL + G. Vấn đề duy nhất của tôi với đầu ra Grid là nó thay đổi các ký tự TAB thành một SPACE duy nhất, vì vậy bạn sẽ mất tất cả các định dạng.
Rick

32

Theo thói quen, tôi đặt LINENO 0ngay sau BEGINtrong các thủ tục đã lưu trữ của mình. Điều này đặt lại số dòng - thành 0, trong trường hợp này. Sau đó, chỉ cần thêm số dòng được thông báo lỗi vào số dòng trong SSMS nơi bạn đã viết LINENO 0và chơi lô tô - bạn có số dòng của lỗi như được trình bày trong cửa sổ truy vấn.


4
Tại sao không chỉ đặt "LineNo X" trong đó X = số dòng bạn đặt câu lệnh, để nó tự động được thêm vào số dòng được báo cáo?
LarryBud

8

Nếu bạn sử dụng Khối bắt và sử dụng RAISERROR () để xác thực bất kỳ mã nào trong Khối thử thì Dòng Lỗi sẽ được báo cáo ở vị trí Khối bắt chứ không phải nơi xảy ra lỗi thực sự. Tôi đã sử dụng nó như thế này để làm rõ điều đó.

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

Trên thực tế điều này Error_number()hoạt động rất tốt.

Hàm này bắt đầu đếm từ câu lệnh GO (Batch Separator) cuối cùng, vì vậy nếu bạn chưa sử dụng bất kỳ dấu cách Go nào và nó vẫn hiển thị số dòng sai - thì hãy thêm 7 vào nó, như trong quy trình được lưu trữ ở dòng số 7, dấu phân tách hàng loạt được sử dụng tự động. Vì vậy, nếu bạn sử dụng chọn Cast (Error_Number () + 7 as Int) làm [Error_Number] - bạn sẽ nhận được câu trả lời mong muốn.


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.- điều này có nghĩa là gì?
underscore_d

4

Trong TSQL / Thủ tục được lưu trữ

Bạn có thể gặp lỗi như:

Msg 206, Cấp độ 16, Trạng thái 2, Quy trình myproc, Dòng 177 [Dòng Bắt đầu Batch 7]

Điều này có nghĩa là lỗi nằm trên dòng 177 trong lô. Không phải 177 trong SQL. Bạn sẽ thấy số dòng mà lô của bạn bắt đầu vào, trong trường hợp của tôi là [7], và sau đó bạn thêm giá trị đó vào số dòng để tìm câu lệnh nào là sai


2

bạn có thể sử dụng cái này

CAST(ERROR_LINE() AS VARCHAR(50))

và nếu bạn muốn tạo bảng nhật ký lỗi, bạn có thể sử dụng cái này:

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())

4
Lưu ý rằng ERROR_LINE () chỉ khả dụng trong phần CATCH của một THỬ / MÈO trong quy trình được lưu trữ. Số dòng mà nó báo cáo giống với số mà SQL Server trả về nếu bạn không bắt được lỗi. Vì vậy, trong khi điều đó có thể hữu ích, nó không giúp giải quyết câu hỏi này.
Rick

1

Câu trả lời dài: số dòng được tính từ CREATE PROCEDURE câu lệnh, cộng với bất kỳ dòng trống hoặc dòng nhận xét nào mà bạn có thể đã có ở trên nó khi thực sự chạy CREATEcâu lệnh, nhưng không tính bất kỳ dòng nào trước một GOcâu lệnh…

Tôi thấy việc tạo một proc được lưu trữ để chơi xung quanh dễ dàng hơn nhiều để xác nhận:

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

Sau khi tạo xong, bạn có thể chuyển sang ALTER PROCEDURE và thêm một số dòng trống phía trên nhận xét và bên trên và bên dưới GOcâu lệnh đầu tiên để xem hiệu quả.

Một điều rất lạ mà tôi nhận thấy là tôi phải chạy EXEC ErrorTestingtrong một cửa sổ truy vấn mới thay vì đánh dấu nó ở cuối cửa sổ đó và chạy… Khi tôi làm điều đó, số dòng tiếp tục tăng lên! Không chắc tại sao điều đó lại xảy ra ..


1

bạn có thể nhận được thông báo lỗi và dòng lỗi trong khối bắt như sau:

'Ms Sql Server Error: - ' + ERROR_MESSAGE() + ' - Error occured at: ' + CONVERT(VARCHAR(20),  ERROR_LINE())
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.