Tsql 在选择之前保证T-SQL存储过程插入?

Tsql 在选择之前保证T-SQL存储过程插入?,tsql,sql-server-2008,Tsql,Sql Server 2008,我有一个从SQLServer2008数据库检索敏感信息的存储过程。我想修改这个过程,以便在任何时候调用它时,它都会在一个单独的表中记录有关谁调用它的信息 我认为下面的方法可以奏效: declare @account varchar(255); set @account = (SELECT SYSTEM_USER); INSERT into AUDIT_LOG(ACCOUNT, TSTAMP) VALUES(@account, getdate()) ; --Now fetch data SEL

我有一个从SQLServer2008数据库检索敏感信息的存储过程。我想修改这个过程,以便在任何时候调用它时,它都会在一个单独的表中记录有关谁调用它的信息

我认为下面的方法可以奏效:

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;
我的问题是,客户端应用程序可以对此存储过程发出调用并获取敏感信息,但不能提交连接,并且插入永远不会发生

有没有办法强制在选择之前插入

我正在使用SQLServer2008

谢谢,
卡尔

为什么不使用?

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

只有在事务已启动时才进行提交

因此,您可以先测试打开的事务,然后禁止读取。这将确保没有打开的事务可回滚。我在这里用过XACT_STATE

使用SET-XACT_-ABORT-ON和TRY/CATCH-too意味着日志的插入也必须在读取发生之前发生。插入时的任何错误都将转到CATCH块。因此,不读取和记录失败本身也可以被记录

所以:这是您在登录时对只读的保证

拥有一个显式事务并没有帮助:不管怎样,插入是一个原子操作。如果被调用方打开事务,则可以回滚日志条目

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

在表中插入记录时,您应该能够获得ast插入值的SCOPE_标识。在执行此操作之前,请从敏感信息中选择x、y、z;您可以检查SCOPE\u IDENTITY>0,然后只执行SELECT语句。

谢谢,这很有效。我的问题有点复杂,因为我使用Python的adodbapi模块作为客户机,它自动启动了一个事务,但我发现了一个禁用它的方法。您的解决方案工作得很好,因为如果客户端不遵守规则,服务器就不会显示数据。我最初已经看过了,但审计信息似乎不能存储在数据库表中。我不确定原因是什么,但我并不觉得在Windows事件日志上卑躬屈膝有多有趣。不过,我可能会将此方法与另一种方法结合使用。我尝试了显式事务,但没有得到预期的结果。我认为敏感数据仍然被提供,但我必须返回并验证。我进行了双重检查-尽管在BEGIN TANSACTION/COMMIT事务中包装了INSERT和SELECT,但在客户端未提交时从未插入该行。有趣的是,表中有一个标识列,下一次插入表时确实跳过了序列中的一个数字。这似乎是一个好主意,但我尝试了一下,结果没有达到预期效果。如果你看我下面的评论,看起来标识值是递增的,但是如果没有客户端的显式提交,就永远不会插入行。