MSSQL記錄表欄位數據變化的相關SQl

来源:https://www.cnblogs.com/majian8608/archive/2019/10/24/11735305.html
-Advertisement-
Play Games

在軟體實施過程中,也許會有這樣的問題: 表中數據出現非預期的結果,此時不確定是程式問題,哪個程式,存儲過程,觸發器.. 或還是人為修改的結果,此時可以用觸發器對特定的表欄位做跟蹤監視,記錄每次新增,修改,刪除此欄位值的操作詳細信息(含登錄名,主機名,IP地址,執行的TSQL語句,程式名等等), 以利 ...


在軟體實施過程中,也許會有這樣的問題: 表中數據出現非預期的結果,此時不確定是程式問題,哪個程式,存儲過程,觸發器.. 或還是人為修改的結果,此時可以用觸發器對特定的表欄位做跟蹤監視,記錄每次新增,修改,刪除此欄位值的操作詳細信息(含登錄名,主機名,IP地址,執行的TSQL語句,程式名等等), 以利於問題的排查.

 

 

-- 建測試表
CREATE TABLE sto
    (
        id INT NOT NULL, -- 主鍵欄位
        de DATETIME -- 被跟蹤的欄位
            CONSTRAINT pk_sto
            PRIMARY KEY (id)
    );

-- 建日誌表
CREATE TABLE log_sto
    (
        logid      INT          NOT NULL IDENTITY(1, 1), -- 日誌序號(日誌主鍵)
        operate    VARCHAR(10),                          -- 操作類型 如Insert,Update,Delete.
        id         INT,                                  -- 原表ID(主鍵)
        old_de     DATETIME,                             -- de欄位舊值
        new_de     DATETIME,                             -- de欄位新值
        spid       INT          NOT NULL,                -- spid
        login_name VARCHAR(100),                         -- 登錄名
        prog_name  VARCHAR(100),                         -- 程式名
        hostname   VARCHAR(100),                         -- 主機名
        ipaddress  VARCHAR(100),                         -- IP地址
        runsql     VARCHAR(4000),                        -- 執行的TSQL代碼
        UDate      DATETIME -- 操作日期時間
            CONSTRAINT pk_logsto
            PRIMARY KEY (logid)
    );
GO


-- 建跟蹤觸發器
CREATE TRIGGER tr_sto
ON sto
AFTER UPDATE, INSERT, DELETE
AS
    BEGIN
        DECLARE @di TABLE
            (
                et VARCHAR(200),
                pt VARCHAR(200),
                ei VARCHAR(MAX)
            );
        INSERT INTO @di
        EXEC ('dbcc inputbuffer(@@spid)');

        DECLARE @op VARCHAR(10);
        SELECT
            @op = CASE WHEN EXISTS ( SELECT 1 FROM inserted ) AND EXISTS (SELECT 1 FROM deleted)
                            THEN 'Update'
                       WHEN EXISTS ( SELECT 1 FROM inserted ) AND NOT EXISTS (SELECT 1 FROM deleted)
                            THEN 'Insert'
                       WHEN NOT EXISTS(SELECT 1 FROM inserted ) AND EXISTS (SELECT 1 FROM deleted)
                          THEN 'Delete'
                  END;

        IF @op IN (
                      'Update', 'Insert'
                  )
            BEGIN
                INSERT INTO log_sto
                    (
                        operate,
                        id,
                        old_de,
                        new_de,
                        spid,
                        login_name,
                        prog_name,
                        hostname,
                        ipaddress,
                        runsql,
                        UDate
                    )
                            SELECT
                                @op,
                                n.id,
                                o.de,
                                n.de,
                                @@spid,
                                (
                                    SELECT
                                        login_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        program_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        hostname
                                    FROM
                                        sys.sysprocesses
                                    WHERE
                                        spid = @@spid
                                ),
                                (
                                    SELECT
                                        client_net_address
                                    FROM
                                        sys.dm_exec_connections
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT TOP 1
                                        ISNULL(ei, '')
                                    FROM
                                        @di
                                ),
                                GETDATE()
                            FROM
                                inserted n
                                LEFT JOIN
                                    deleted o
                                        ON o.id = n.id;
            END;
        ELSE
            BEGIN
                INSERT INTO log_sto
                    (
                        operate,
                        id,
                        old_de,
                        new_de,
                        spid,
                        login_name,
                        prog_name,
                        hostname,
                        ipaddress,
                        runsql,
                        UDate
                    )
                            SELECT
                                @op,
                                o.id,
                                o.de,
                                NULL,
                                @@spid,
                                (
                                    SELECT
                                        login_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        program_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        hostname
                                    FROM
                                        sys.sysprocesses
                                    WHERE
                                        spid = @@spid
                                ),
                                (
                                    SELECT
                                        client_net_address
                                    FROM
                                        sys.dm_exec_connections
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT TOP 1
                                        ISNULL(ei, '')
                                    FROM
                                        @di
                                ),
                                GETDATE()
                            FROM
                                deleted o;
            END;
    END;
GO


--> 測試DML操作

-- 操作1
INSERT INTO sto
    (
        id,
        de
    )
VALUES
    (
        1, '2012-01-01 05:06:07'
    );
GO

-- 操作2
INSERT INTO sto
    (
        id,
        de
    )
VALUES
    (
        2, '2012-01-01 06:06:07'
    );
GO

-- 操作3
UPDATE
    sto
SET
    de = getdate()
WHERE
    id = 2;
GO

-- 操作4
UPDATE
    sto
SET
    de = getdate()
WHERE
    id = 1;
GO

-- 操作5
INSERT INTO sto
    (
        id,
        de
    )
VALUES
    (
        5, '2012-01-01 15:26:37'
    );
GO

-- 操作6
DELETE sto
WHERE
    id = 2;
GO




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 宿主機連接wifi,虛擬機無法聯網 查看是否有網路圖標 操作一: sudo service network-manager stopsudo rm /var/lib/NetworkManager/NetworkManager.statesudo service network-manager sta ...
  • 項目中需要一個聊天室的功能,所以需要websocket通信,選擇了使用 模塊,主要記錄下 部署的配置和一些坑. 原項目是通過nginx+uwsgi部署的,這裡我沒做任何改動,只是通過Nginx將特定請求路徑代理到daphne上.部署前對 配置的一些修改可以直接參考 "官方文檔" ,這個比較簡單,也沒 ...
  • 1、關閉HDMI輸出 /opt/vc/bin/tvservice -o 2、關閉模塊 vi /etc/modules #snd-bcm2835 ...
  • 以msm8909為例,高通的主要文件有幾個: qpnp linear charger.c(線性充電器) qpnp vm bms.c(BMS管理) power_supply_core.c(power_supply對外部提供對應介面) 其中,vm_bus的power_supply一般為struct po ...
  • 1、終端無法輸入中文的原因(未實踐) 原文地址 2、Windows10下VMwarm(V15.5)和ubuntu14.04實現複製文件(已經實踐) 轉載路徑 ...
  • 一、安裝編譯工具及庫文件 zlib庫:zlib庫是ngx_http_gzip_module(gzip壓縮模塊)所必需的openssl庫 :--with-http_ssl_module使用該模塊必需裝openssl庫,來實現http支持https協議 二、安裝pcre庫prce庫:--with-htt ...
  • 完全卸載gitlab 1.停止gitlab # gitlab-ctl stop 2.卸載gitlab(看是gitlab-ce版本還是gitlab-ee版本) # rpm -e gitlab-ce 3.查看gitlab進程 # ps aux | grep gitlab 4.殺掉第一個進程 # kill ...
  • Editor: Veagau Time: 2019/10/17 [TOC] 一、PyTorch虛擬環境配置 該部分操作均在終端(terminal)命令行中執行,在桌面右擊滑鼠新建terminal即可。 若系統已經安裝Anaconda,則可以跳過第一步(檢驗方法:命令行執行conda list,有返回 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...