[英]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.