在SELECT之前保证T-SQL存储过程INSERT?

时间:2011-06-17 13:20:39

标签: tsql sql-server-2008

我有一个存储过程,用于从SQL Server 2008数据库中检索敏感信息。我想修改程序,以便在调用时,它会在单独的表中记录有关谁调用它的信息。

我认为以下内容可行:

declare @account varchar(255);
set @account = (SELECT SYSTEM_USER);

INSERT into AUDIT_LOG(ACCOUNT, TSTAMP)
VALUES(@account, getdate())
;

--Now fetch data
SELECT x,y,z from sensitive_info;

我的问题是客户端应用程序可以发出对此存储过程的调用并获取敏感信息,但提交连接并且INSERT永远不会发生!

有没有办法强制INSERT在SELECT之前发生?

我正在使用SQL Server 2008。

谢谢, 卡尔

4 个答案:

答案 0 :(得分:2)

您只有在事务已启动时才会执行COMMIT。

因此,您可以先测试打开的事务,然后禁止读取。这将确保不会打开任何事务回滚。我在这里使用了XACT_STATE()

使用SET XACT_ABORT ON和TRY / CATCH也意味着在读取发生之前,的INSERT必须发生。 INSERT上的任何错误将转到CATCH块。所以没有读取和记录失败本身也可以记录。

所以:这是你保证“只记录后读取”

拥有显式事务无济于事:INSERT无论如何都是原子操作。如果被调用打开事务,则可以回滚日志条目

CREATE PROC getSecretStuff
AS
SET NOCOUNT, XACT_ABORT ON;

BEGIN TRY
    IF XACT_STATE() <> 0
       RAISERRROR ('Call not allowed in an active transaction', 16, 1)

    INSERT into AUDIT_LOG(ACCOUNT, TSTAMP)
    VALUES(SYSTEM_USER, getdate());

    --Now fetch data
    SELECT x,y,z from sensitive_info;

END TRY
BEGIN CATCH
    --     error handling etc
END CATCH
GO

答案 1 :(得分:1)

为什么不使用build in auditing functionality

答案 2 :(得分:0)

您是否尝试过使用显式事务并在commit语句后执行select?

答案 3 :(得分:0)

在表格中插入记录时,您应该获得ast插入值的SCOPE_IDENTITY()。在从sensitive_info执行SELECT x,y,z之前;你可以查看SCOPE_IDENTITY()&gt; 0然后只执行SELECT语句。