代码之家  ›  专栏  ›  技术社区  ›  hgulyan

最佳实践-存储过程日志记录

  •  21
  • hgulyan  · 技术社区  · 14 年前

    如果您有一个长时间运行的SP,您是以某种方式记录它的操作,还是只是等待此消息?

    “命令已成功完成。”

    我想在这个问题上有很多解决方案,但是有没有最佳实践——一个经常使用的简单的解决方案?

    编辑

    我在这个问题上找到了一个有趣的链接

    http://weblogs.sqlteam.com/brettk/archive/2006/09/21/12391.aspx

    文章描述了使用日志表,但有一个问题

    日志记录过程必须在任何事务之外执行

    我不能在外部调用这个insert,因为我使用的是光标,并且在每一行的表中插入一行。

    有什么想法吗?

    编辑2

    挖。。

    有一个 xp_logevent 在SQLServer中。你试过了吗?

    怎么样 事件探查器 ?

    还有 Creating Log file for Stored Procedure

    4 回复  |  直到 6 年前
        1
  •  22
  •   Martin Smith    14 年前

    如何调用存储过程?如果是通过ManagementStudio,那么您可以轻松地按如下方式打印消息

    RAISERROR ('Some debugging info', 0, 1) WITH NOWAIT
    

    这比使用 PRINT 因为消息将立即出现。这些消息也可以通过连接 Connection.InfoMessage 事件。

    我看到您已经将SQL事件探查器列为一种可能性。你可能有兴趣知道你可以 log your own user configurable events 可以在SQL事件探查器中看到。

        2
  •  8
  •   Jean-François Gravel dalenewman    6 年前

    为了查看正在进行的操作有多长,以及上一个操作修改了多少行,我将当前日期+时间和最后一行计数添加到每个条目中。我使用以下程序:

    CREATE PROCEDURE dbo.[Log]
        @Message NVARCHAR(512),
        @RowCount INT = null OUTPUT,
        @Delimiter NCHAR(1) = N' ',
        @PadChar NCHAR(1) = N'-'
    AS
        BEGIN
            SET @RowCount = @@ROWCOUNT;
    
            DECLARE @LogDate AS NVARCHAR(50);
            DECLARE @RowCountPadded AS NCHAR(8);
    
            SET @LogDate = CONVERT(NVARCHAR(50),GETDATE(),121);
            SELECT @RowCountPadded = CASE @RowCount WHEN 0 THEN REPLICATE(@PadChar,8) ELSE REPLACE(STR(@RowCount, 8), SPACE(1), @PadChar) END; 
    
            SET @Message = @LogDate + @Delimiter + @RowCountPadded + @Delimiter + @Message;
            RAISERROR (@Message, 0, 1) WITH NOWAIT;
        END
    

    因此,在您的过程中,添加如下日志输出:

    EXEC dbo.[Log] 'the message';
    

    它产生了:

    2012-12-28 11:28:25.197 -------- the message
    

    如果您以前执行过一些操作,您将看到破折号所在的行数。如果您需要其他内容的行计数(例如,为了记录到表中),可以将它作为输出参数从过程中获取。

    更新 使用这个 gist 如果您想创建一次这个过程并在任何地方使用它。

    --删除的行---

        3
  •  3
  •   Joe    14 年前

    我们通常使用日志记录表并关注事务。我们几乎避免了涉及到SQL Server外部的任何事情(例如,写入文件系统、调用外部服务、NET程序集等)。

    我们还试图避免使用光标——您的过程是否可能因为效率低下而长时间运行?

        4
  •  2
  •   FLICKER    9 年前

    我用这个程序

    CREATE PROCEDURE dbo.PrintLog (
        @Msg VARCHAR(2048)
        , @Option VARCHAR(100) = ''
        , @Separator VARCHAR(10) = '-'
        )
    /*
    @Option is a string containing possible values as B,A,D,T
    if you want to print separator before message, include B
    if you want to print separator after message, include A
    if you want to print date, include D
    if you want to print time, include T
    Sample: 'BAD'
    
    The order of characters does not matter. it is not case sensitive
    
    Usage:
        exec dbo.PrintLog 'Timed Log', 'T'
        exec dbo.PrintLog 'Dated Log', 'D'
        exec dbo.PrintLog 'With Separator and Time', 'BT', '><'
        exec dbo.PrintLog 'With Separator and Date', 'BAD', '*'
        exec dbo.PrintLog 'With Separator and DateTime', 'BADT', 'x'
    */
    AS
    BEGIN
        declare @tempStr varchar(100)
        set @tempStr = replicate(@Separator, 50)
        IF charindex('B', upper(@Option)) > 0
            raiserror (@tempStr, 10, 1) with nowait
    
        DECLARE @prompt VARCHAR(max) = ''
    
        IF charindex('D', upper(@Option)) > 0
            SET @prompt = convert(VARCHAR, SysDatetime(), 101) + ' '
    
        IF charindex('T', upper(@Option)) > 0
            SET @prompt = @prompt + convert(VARCHAR, SysDatetime(), 108) + ' '
        SET @prompt = @prompt + @Msg
    
        raiserror (@prompt, 10, 1) with nowait
    
        set @tempStr = replicate(@Separator, 50)
        IF charindex('A', upper(@Option)) > 0
            raiserror (@tempStr, 10, 1) with nowait
    
        RETURN
    END
    
    GO
    

    用法

        exec dbo.PrintLog 'Date and Timed Log', 'DT'
        exec dbo.PrintLog 'Dated Log', 'D'
        exec dbo.PrintLog 'With Separator and Time', 'BT', '><'
        exec dbo.PrintLog 'With Separator and Date', 'BAD', '*'
        exec dbo.PrintLog 'With Separator and DateTime', 'BADT', 'x'
    

    还可以将参数默认值更改为所需的值。