Table 具有存储过程 ID 的审计触发器
Table Audit Trigger with Stored Procedure ID
我有一个由深入几层的存储过程启动的过程。最多可能涉及 12 个后续存储过程。
我有一个 table 在上述过程中错误地更新了列,我想找出哪个存储过程是进行错误更新的。
我查看了 table 通过触发器进行的审计,并尝试使用 SCOPE_IDENTITY 函数来确定哪个存储过程是罪魁祸首,但它 returns 我的审计 [=NULL 值=26=]。
我想做的事情可行吗?我基本上是在尝试使用它而不是调试,而调试在过去取得了有限的成功,而且我不想编辑存储过程来捕获信息。
这是我的代码:我创建了一个测试存储过程来更新有问题的 table。
--Create test Sproc
IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 'usp_update_pkd')
BEGIN
DROP PROCEDURE usp_update_pkd
END
GO
CREATE PROCEDURE usp_update_pkd
@p_order_number VARCHAR(30)
AS
UPDATE t_pick_detail
SET status = 'XXX'
WHERE order_number = @p_order_number
RETURN
GO
--Create Audit Table
IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 't_pkd_audit')
BEGIN
DROP TABLE t_pkd_audit
END
GO
CREATE TABLE t_pkd_audit
(
order_audit_id INTEGER IDENTITY(1,1) PRIMARY KEY,
wave_id VARCHAR(10),
work_type VARCHAR(20),
order_number VARCHAR(20),
sproc_id NVARCHAR(128),
updated_on DATETIME
)
GO
--Create Trigger
IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 'pkd_audit_record')
BEGIN
DROP TRIGGER pkd_audit_record
END
GO
CREATE TRIGGER pkd_audit_record ON t_pick_detail
AFTER UPDATE
AS
BEGIN
INSERT INTO t_pkd_audit
(wave_id, work_type, order_number, sproc_id, updated_on )
SELECT DISTINCT i.wave_id, i.work_type, i.order_number, CAST(SCOPE_IDENTITY() AS VARCHAR), GETDATE()
FROM t_pick_detail t
INNER JOIN inserted i
ON t.order_number = i.order_number
AND t.line_number = i.line_number
END
GO
--Execute test SProc
EXEC usp_update_pkd '4045'
--Check Results
SELECT * FROM t_pkd_audit (NOLOCK)
--Result Set
order_audit_id|wave_id|work_type|order_number|sproc_id|updated_on
1 |NULL |17 |4045 |NULL |2017-06-22 00:47:52.513
非常感谢任何帮助。
向您的审核添加一列 table,其中将包含存储过程名称。因为它有一个默认值,所以你不需要改变你的触发器,但如果你愿意,你可以删除 sproc_id。默认值将采用存储在 context_info 中的 @@PROCID 并使用它来获取存储过程名称。
CREATE TABLE t_pkd_audit
(
order_audit_id INTEGER IDENTITY(1,1) PRIMARY KEY,
wave_id VARCHAR(10),
work_type VARCHAR(20),
order_number VARCHAR(20),
sproc_id NVARCHAR(128),
updated_on DATETIME,
SpName [varchar](128) NULL CONSTRAINT [DF_a_hist_sourceName] DEFAULT (object_name(CONVERT([int],CONVERT([varbinary](4),context_info()))))
)
对于 12 个存储过程中的每一个,开始于:
declare @calledBy varbinary(128) = coalesce(Context_info(),0),@proc int
select @proc = @@PROCID
set context_info @proc
它会将存储过程的id放在context_info中,并将父存储过程的id存储在一个变量中。
在每个存储过程结束时。如果您使用 returns,那么在每个 return 之前添加以下代码以在 context_info.
中写回父存储过程的 ID
set context_info @calledby
我有一个由深入几层的存储过程启动的过程。最多可能涉及 12 个后续存储过程。
我有一个 table 在上述过程中错误地更新了列,我想找出哪个存储过程是进行错误更新的。
我查看了 table 通过触发器进行的审计,并尝试使用 SCOPE_IDENTITY 函数来确定哪个存储过程是罪魁祸首,但它 returns 我的审计 [=NULL 值=26=]。
我想做的事情可行吗?我基本上是在尝试使用它而不是调试,而调试在过去取得了有限的成功,而且我不想编辑存储过程来捕获信息。
这是我的代码:我创建了一个测试存储过程来更新有问题的 table。
--Create test Sproc
IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 'usp_update_pkd')
BEGIN
DROP PROCEDURE usp_update_pkd
END
GO
CREATE PROCEDURE usp_update_pkd
@p_order_number VARCHAR(30)
AS
UPDATE t_pick_detail
SET status = 'XXX'
WHERE order_number = @p_order_number
RETURN
GO
--Create Audit Table
IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 't_pkd_audit')
BEGIN
DROP TABLE t_pkd_audit
END
GO
CREATE TABLE t_pkd_audit
(
order_audit_id INTEGER IDENTITY(1,1) PRIMARY KEY,
wave_id VARCHAR(10),
work_type VARCHAR(20),
order_number VARCHAR(20),
sproc_id NVARCHAR(128),
updated_on DATETIME
)
GO
--Create Trigger
IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 'pkd_audit_record')
BEGIN
DROP TRIGGER pkd_audit_record
END
GO
CREATE TRIGGER pkd_audit_record ON t_pick_detail
AFTER UPDATE
AS
BEGIN
INSERT INTO t_pkd_audit
(wave_id, work_type, order_number, sproc_id, updated_on )
SELECT DISTINCT i.wave_id, i.work_type, i.order_number, CAST(SCOPE_IDENTITY() AS VARCHAR), GETDATE()
FROM t_pick_detail t
INNER JOIN inserted i
ON t.order_number = i.order_number
AND t.line_number = i.line_number
END
GO
--Execute test SProc
EXEC usp_update_pkd '4045'
--Check Results
SELECT * FROM t_pkd_audit (NOLOCK)
--Result Set
order_audit_id|wave_id|work_type|order_number|sproc_id|updated_on
1 |NULL |17 |4045 |NULL |2017-06-22 00:47:52.513
非常感谢任何帮助。
向您的审核添加一列 table,其中将包含存储过程名称。因为它有一个默认值,所以你不需要改变你的触发器,但如果你愿意,你可以删除 sproc_id。默认值将采用存储在 context_info 中的 @@PROCID 并使用它来获取存储过程名称。
CREATE TABLE t_pkd_audit
(
order_audit_id INTEGER IDENTITY(1,1) PRIMARY KEY,
wave_id VARCHAR(10),
work_type VARCHAR(20),
order_number VARCHAR(20),
sproc_id NVARCHAR(128),
updated_on DATETIME,
SpName [varchar](128) NULL CONSTRAINT [DF_a_hist_sourceName] DEFAULT (object_name(CONVERT([int],CONVERT([varbinary](4),context_info()))))
)
对于 12 个存储过程中的每一个,开始于:
declare @calledBy varbinary(128) = coalesce(Context_info(),0),@proc int
select @proc = @@PROCID
set context_info @proc
它会将存储过程的id放在context_info中,并将父存储过程的id存储在一个变量中。
在每个存储过程结束时。如果您使用 returns,那么在每个 return 之前添加以下代码以在 context_info.
中写回父存储过程的 IDset context_info @calledby