gpt4 book ai didi

sql - 触发器仅将变量的 1 个字符插入表中

转载 作者:行者123 更新时间:2023-12-05 04:00:54 32 4
gpt4 key购买 nike

我有以下 sql 触发器,它根据对相关表发生的删除操作将数据插入到名为 PS_AUDIT_PSROLEUSR 的表中。

当表更新由应用程序中的在线用户触发时(角色行被删除)然后整个 OPRID 被正确插入到 PS_AUDIT_PSROLEUSR 中,但是当触发器通过批处理程序运行时我已经写好了,它只是获取AUDIT_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;

关于sql - 触发器仅将变量的 1 个字符插入表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55854500/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com