C# 如何在SQL Server中创建接受外部参数的触发器?
是否可以编写接受外部参数的触发器 主要原因是,我只能使用一个数据库用户连接到数据库。现在我正在开发一个数据库应用程序,并为每个单独的表创建了触发器来存储历史记录 在存储历史数据时,我想存储执行了C# 如何在SQL Server中创建接受外部参数的触发器?,c#,sql,sql-server,C#,Sql,Sql Server,是否可以编写接受外部参数的触发器 主要原因是,我只能使用一个数据库用户连接到数据库。现在我正在开发一个数据库应用程序,并为每个单独的表创建了触发器来存储历史记录 在存储历史数据时,我想存储执行了插入、更新或删除操作的应用程序用户名。我本想使用User\u Name(),但后来知道,它只返回数据库用户,而不返回应用程序用户 因此,我正在寻找一些关于使用外部参数创建触发器的建议,以便将应用程序用户的id传递给该触发器。我想我已经清楚地解释了我的需求。提前谢谢 编辑 外部参数应该类似于存储过程参数,我
插入
、更新
或删除
操作的应用程序用户名。我本想使用User\u Name()
,但后来知道,它只返回数据库用户,而不返回应用程序用户
因此,我正在寻找一些关于使用外部参数创建触发器的建议,以便将应用程序用户的id传递给该触发器。我想我已经清楚地解释了我的需求。提前谢谢
编辑外部参数应该类似于存储过程参数,我们可以在其中传递值 Edit2
可能是我的描述不够清楚。所以我给你举个例子。
我正在开发的Web应用程序与帐户相关。因此,需要跟踪数据的更改。例如,会计人员可以更改员工的工资和佣金信息。如果输入/更新错误的信息,则总体财务结果将产生巨大的负面影响。现在在系统中,用户使用userid和password登录到系统,然后对员工信息进行一些更改。在这一阶段,我希望跟踪谁更改了员工信息、何时更改、更改前的值以及更改完成后的值。因此,将来如果出现任何问题,我可以通过证据找出犯错误的用户。
不一定要使用触发器完成,但也欢迎使用任何其他替代方法。在每个表中存储用户名,并在数据更改期间将其作为参数传递。从那里,触发器可以将数据归档到另一个表中。在您的位置,我将使用此示例,如果您的数据库中有人进行事件更新或选择,您将能够添加一些您想要的信息 示例表:
CREATE TABLE RAF1
(
strona NUMBER,
nazwa VARCHAR2(40)
);
示例触发器(如果您将nazw='same'write nazwa='roland'连接到此表,则此触发器将始终处于激活状态。您可以编辑此示例
create or replace TRIGGER sam
BEFORE INSERT OR UPDATE OF nazwa
ON RAF1 FOR EACH ROW WHEN (new.nazwa = 'same')
BEGIN :new.nazwa := 'ronald'; END
您需要重新设计您的方法。数据库无法只了解您的应用程序用户信息。而且,不,您不能将参数传递给触发器。但您可以使用触发器引用自己的表,因此有一种方法
当您连接到数据库时,每个连接都会获得自己的进程id。您可以通过@spid获得该id 因此,当触发器触发时,您可以使用它来知道是哪个连接导致了更改 使用相同的数据库登录名可以有100个并发连接,每个连接都有自己的@spid值
但是,为了对您有用,您需要准备所有连接。每次建立连接时,您的应用程序都应该写入一个表,以记录应用程序使用该@@spid的内容 也许是像…这样简单的事情
CREATE TABLE
map_spid_application_user (
spid BIGINT,
application VARCHAR(128),
user VARCHAR(128),
PRIMARY KEY (spid)
)
然后,在每个连接上运行类似这样的操作(可能通过存储过程)
然后,在触发器中,您可以引用/加入此表,以找出@spid引用的对象
您还可以变得更加智能,并使用类似的方法来永久记录用户连接的内容,如哪个spid。任何spid的当前用户将始终是具有最新连接日期时间的用户
那时你几乎可以做任何你喜欢的事情。因为你正在创建所有的信息,而不依赖数据库只知道@@spid以外的任何东西。我已经完成了你所描述的。我不能说我对结果感到满意,因为当发生连接共享之类的奇怪事情时,解决方案可能相当脆弱嗯,这也只是感觉不对劲,但如果你愿意,试试看
同样,这会满足您的要求,但我不建议这样做。最好只是将审核信息作为基本插入/更新内容的一部分从客户端或通过存储过程进行管理。因为触发器是按设计niladic模块,这意味着它们不支持参数。一种在外部级别a之间传递信息的技术niladic模块使用上下文信息或会话上下文
Declare @mycontextinfo AS VARBINARY(128) = CAST('Application User Name' AS VARBINARY(128))
SET CONTEXT_INFO @mycontextinfo;
您可以从会话中的任何位置读取上下文信息,包括以下触发器:
SELECT CAST(CONTEXT_INFO() AS VARCHAR(128)) AS mycontextinfo;
另一个最复杂的方法是使用会话上下文
EXEC sys.sp_set_Session_context @key = 'ApplicationUser', @value = 'XXX', @read_only = 1;
然后,当需要从会话中的任何位置读取值时,请使用以下代码:
SELECT SESSION_CONTEXT('ApplicationUser') AS [USER]
请记住,这是在SQL Server 2016中添加的。什么是“应用程序用户ID”?它是SQL登录、Windows帐户还是其他?SYSTEM_USER是否返回您想要的?您从哪里获取应用程序用户?为什么不能在触发器中查找应用程序用户?可能重复使用
上下文_INFO()
,请参阅使用此选项的答案链接。“应用程序用户ID”是用户登录系统时使用的登录id。该id存储在数据库表中。@V.P.Verma您仍然需要更精确,不清楚该登录名是SQL Server登录名、Windows帐户还是完全由您的应用程序管理的。如果是SQL或Windows,则system_用户将返回该id;如果是您的内部登录名你的申请,那么你需要遵循这里的其他建议之一(上面来自KM的关于usi的建议)
SELECT SESSION_CONTEXT('ApplicationUser') AS [USER]