web-dev-qa-db-ja.com

トリガーを起動するSQL Server監査クエリ

SQL Serverを使用して、トリガー内からトリガーするSQLを監査する方法はありますか?

プロファイラーなしでデータベースに対してトリガーを起動するSQLクエリを知る必要があります。

ありがとう

5
jviladrich

これを実行するトリガーがいくつかあり、DBCC INPUTBUFFERは一般的にそれを行うための最良の方法です。注意:出力は4000文字に制限されています。非常に長いクエリは切り捨てられます。

DECLARE @sql nvarchar(max)
SET @sql = 'DBCC INPUTBUFFER(' + CAST(@@SPID AS nvarchar(100)) + ')'
CREATE TABLE #SQL (
    EventType varchar(100),
    Parameters int,
    EventInfo nvarchar(max)
)
INSERT INTO #SQL
EXEC sp_executesql @sql

SELECT @sql = EventInfo FROM #SQL
DROP TABLE #SQL

この最後に、@sqlには、現在のリクエストのクエリが含まれます。また、一時テーブルの代わりにテーブル変数を簡単に使用することもできます。

4
db2

SQLクエリもキャプチャするDDLトリガーのサンプルを次に示します。

CREATE TRIGGER Audit_DDL
ON DATABASE
    FOR CREATE_TABLE, ALTER_TABLE, DROP_TABLE
AS
     DECLARE
        @event xml;
     SET
     @event = EVENTDATA();
     INSERT INTO Audit_DDL_Events
     VALUES
     (
     REPLACE(CONVERT(varchar(50),
     @event.query('data(/EVENT_INSTANCE/PostTime)')), 'T', ' ')
     ,
     CONVERT(varchar(150),
     @event.query('data(/EVENT_INSTANCE/LoginName)'))
     ,
     CONVERT(varchar(150),
     @event.query('data(/EVENT_INSTANCE/UserName)'))
     ,
     CONVERT(varchar(150),
     @event.query('data(/EVENT_INSTANCE/DatabaseName)'))
     ,
     CONVERT(varchar(150),
     @event.query('data(/EVENT_INSTANCE/SchemaName)'))
     ,
     CONVERT(varchar(150),
     @event.query('data(/EVENT_INSTANCE/ObjectName)'))
     ,
     CONVERT(varchar(150),
     @event.query('data(/EVENT_INSTANCE/ObjectType)'))
     ,
     CONVERT(varchar(max),
     @event.query('data(/EVENT_INSTANCE/TSQLCommand/CommandText)'))
     );

適切な表の結果:

CREATE TABLE Audit_DDL_Events
(
             DDL_Event_Time            datetime
             ,
             DDL_Login_Name            varchar(150)
             ,
             DDL_User_Name             varchar(150)
             ,
             DDL_Database_Name         varchar(150)
             ,
             DDL_Schema_Name           varchar(150)
             ,
             DDL_Object_Name           varchar(150)
             ,
             DDL_Object_Type           varchar(150)
             ,
             DDL_Command              varchar(max)
);

次のようになります:

enter image description here

3
Ivan Stankovic

以下は、現在のバッチ/ステートメントを取得するトリックを行うようです:

SELECT current_batch     = dest.text
     , current_statement = SUBSTRING(dest.text, dem.statement_start_offset/2, CASE WHEN dem.statement_end_offset=-1 THEN 8000 ELSE (dem.statement_end_offset-dem.statement_start_offset)/2 END)
FROM   sys.dm_exec_requests dem CROSS APPLY sys.dm_exec_sql_text(dem.sql_handle) dest
WHERE  session_id = @@SPID

iIRCが呼び出しがストアドプロシージャに対するものである場合、要求の送信方法(アドホックSQL、準備されたプロシージャ呼び出しなど)によっては、呼び出しのテキストではなく、プロシージャのコードが返される場合があります。トリガーで、探しているものではなくトリガーのコードを取得することになるかどうかは不明なので、テストする必要があります。

バッチとステートメントの違いを確認するには、次のように実行します。

DECLARE @current_batch NVARCHAR(MAX), @current_statement NVARCHAR(MAX)
-- start of statement that will be returned by itself
SELECT @current_batch     = dest.text
     , @current_statement = SUBSTRING(dest.text, dem.statement_start_offset/2, CASE WHEN dem.statement_end_offset=-1 THEN 8000 ELSE (dem.statement_end_offset-dem.statement_start_offset)/2 END)
FROM   sys.dm_exec_requests dem CROSS APPLY sys.dm_exec_sql_text(dem.sql_handle) dest
WHERE  session_id = @@SPID
-- end of statement that will be returned by itself
-- results:
PRINT '---- BATCH --------------------------------------------'
PRINT @current_batch
PRINT '---- STATEMENT ----------------------------------------'
PRINT @current_statement

sQL Server Management Studioなどを使用します。

3
David Spillett