簡體   English   中英

觸發僅將變量的 1 個字符插入表中

[英]Trigger only inserting 1 character of variable into table

我有以下 sql 觸發器,它根據相關表上發生的刪除操作將數據插入名為PS_AUDIT_PSROLEUSR表中。

當應用程序中的在線用戶觸發表更新時(刪除角色行),然后整個 OPRID 正確插入到PS_AUDIT_PSROLEUSR ,但是當觸發器通過我編寫的批處理程序運行時,它只獲取第一個字母AUDIT_OPRID 我通過在另一個OPRID下運行程序來確認這OPRID ,它仍然只將第一個字符插入到列中。 請原諒我對 SQL 觸發器不是很熟悉。

ALTER TRIGGER [dbo].[PSROLEUSER_TR] 
ON [dbo].[PSROLEUSER]
FOR INSERT, UPDATE, DELETE
AS
    SET NOCOUNT ON

    DECLARE @XTYPE CHAR(1), @OPRID CHAR(30)

    SET @OPRID = NULL

    SELECT @OPRID = CASE(CHARINDEX(',', CAST(context_info AS CHAR(128))))
                       WHEN 0 THEN 'Native SQL'
                       ELSE SUBSTRING(CAST(context_info AS CHAR(128)), 1, (CHARINDEX(',', CAST(context_info AS CHAR(128)))-1))
                    END
    FROM sys.sysprocesses
    WHERE spid = @@spid

    -- Determine Transaction Type
    IF EXISTS (SELECT * FROM DELETED)
    BEGIN
        SET @XTYPE = 'D'
    END

    IF EXISTS (SELECT * FROM INSERTED)
    BEGIN
        IF (@XTYPE = 'D')
        BEGIN
            SET @XTYPE = 'U'
        END
        ELSE
        BEGIN
            SET @XTYPE = 'I'
        END
    END

    -- Transaction is a Delete
    IF (@XTYPE = 'D')
    BEGIN
        INSERT INTO PS_AUDIT_PSROLEUSR (AUDIT_OPRID, AUDIT_STAMP, AUDIT_ACTN, ROLEUSER, ROLENAME, DYNAMIC_SW)
            SELECT 
                @OPRID, 
                DATEADD(SECOND, ROW_NUMBER() OVER (ORDER BY @OPRID), GETDATE()), 
                'D', ROLEUSER, ROLENAME, DYNAMIC_SW 
            FROM 
                deleted 
    END

    -- Transaction is a Insert
    IF (@XTYPE = 'I')
    BEGIN
        INSERT INTO PS_AUDIT_PSROLEUSR (AUDIT_OPRID, AUDIT_STAMP, AUDIT_ACTN, ROLEUSER, ROLENAME, DYNAMIC_SW)
             SELECT 
                 @OPRID, GETDATE(),
                 'A', ROLEUSER, ROLENAME, DYNAMIC_SW 
             FROM 
                 inserted 
    END

    -- Transaction is a Update
    IF (@XTYPE = 'U')
    BEGIN
        -- Before Update
        INSERT INTO PS_AUDIT_PSROLEUSR (AUDIT_OPRID, AUDIT_STAMP, AUDIT_ACTN, ROLEUSER, ROLENAME, DYNAMIC_SW)
            SELECT 
                @OPRID, GETDATE(), 'K',
                ROLEUSER, ROLENAME, DYNAMIC_SW 
            FROM 
                deleted 
        -- After Update
        INSERT INTO PS_AUDIT_PSROLEUSR (AUDIT_OPRID, AUDIT_STAMP, AUDIT_ACTN, ROLEUSER, ROLENAME, DYNAMIC_SW)
            SELECT 
                @OPRID, GETDATE(), 'N',
                ROLEUSER, ROLENAME, DYNAMIC_SW 
            FROM 
                inserted 
    END

PS_AUDIT_PSROLEUSR

AUDIT_OPRID AUDIT_STAMP              AUDIT_ACTN ROLEUSER    ROLENAME    DYNAMIC_SW
K           2019-04-25 08:33:08.340  D          LTESTUSER   EUSER       N
K           2019-04-25 08:33:09.340  D          LTESTUSER   EPRO        N

我似乎無法訪問SELECT * FROM DELETED的“DELETE”表,所以我不確定這是否只是在運行時動態生成的。

旁注 - 奇怪的是,我按如下方式查詢 PS_AUDIT_PSROLEUSR 的值 'K' 我得到 0 行返回。 我已經檢查過字母后面沒有尾隨空格。

    SELECT *
    FROM PS_AUDIT_PSROLEUSR
    WHERE AUDIT_OPRID = 'K'

如果我使用LIKE運算符,我只會獲取“K”的數據

-- Results in 0 rows

編輯:如果我運行以下代碼,我將獲得 12 個字符長度的行插入 'K' 所以有些東西會添加額外的尾隨空格...

SELECT LEN(AUDIT_OPRID),*
FROM PS_AUDIT_PSROLEUSR
WHERE AUDIT_OPRID  like 'K%'  

我還嘗試將這個簡單的 IF 語句添加到觸發器中,但它似乎也不起作用:我認為將二進制 (context_info) 轉換為 varchar 將允許邏輯過濾掉值“K”。

IF (CONVERT(VARCHAR(256),@OPRID)) <> 'K' 
BEGIN

這不一定是觸發器的問題,而是由批處理應用程序設置的CONTEXT_INFO二進制值的字符編碼。 CONTEXT_INFO值實際上是一個 Unicode 字符串並且隨后在 T-SQL 中將二進制值轉換為CHAR時,您將得到這些症狀。

考慮這個例子:

DECLARE @ContextInfo varbinary(128) = CAST(N'ABC,DEF,GHI' AS varbinary(128));
SET CONTEXT_INFO @ContextInfo;
GO

DECLARE @OPRID CHAR(30) = NULL;
SELECT CAST(context_info AS CHAR(30)) AS CharValue, CAST(context_info AS NCHAR(30)) AS NCharValue 
FROM sys.sysprocesses
WHERE spid = @@spid;
GO

結果:

+-----------+-------------+
| CharValue | NCharValue  |
+-----------+-------------+
| A         | ABC,DEF,GHI |
+-----------+-------------+

為了解決這個問題,你既可以在應用程序代碼集改變CONTEXT_INFO成ANSI字符串或更改T-SQL CASE表達式來CAST值作為NCHAR 下面是執行此操作的 T-SQL 示例,並且還使用sys.dm_exec_sessions DMV 而不是sys.processes ,后者已被棄用 15 年。

SELECT @OPRID = CASE(CHARINDEX(',', CAST(context_info AS NCHAR(64))))
                   WHEN 0 THEN N'Native SQL'
                   ELSE SUBSTRING(CAST(context_info AS NCHAR(64)), 1, (CHARINDEX(',', CAST(context_info AS NCHAR(64)))-1))
                END
FROM sys.dm_exec_sessions
WHERE session_id = @@spid;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM