テーブルに行がある場合、テーブルを削除しないようにしたい。
私が書いた:
create trigger prevDrop on database for drop_table
as
begin
if exists (select * from dropped_table)
raiserror('cant do',25,1)
end
しかし、で構文エラーが発生しますdropped table
。
削除しようとしているテーブルを追跡するにはどうすればよいですか?
テーブルに行がある場合、テーブルを削除しないようにしたい。
私が書いた:
create trigger prevDrop on database for drop_table
as
begin
if exists (select * from dropped_table)
raiserror('cant do',25,1)
end
しかし、で構文エラーが発生しますdropped table
。
削除しようとしているテーブルを追跡するにはどうすればよいですか?
この場合はアフタートリガーであるため、DDLトリガーでこれを行うことはできないと思います。そのため、テーブルは存在しなくなり、システムメタデータにはその痕跡がありません。空でないテーブルだけでなく、すべてのテーブルをドロップしないようにしないのはなぜですか?
CREATE TRIGGER prevDrop ON DATABASE
FOR DROP_TABLE
AS
BEGIN
ROLLBACK;
RAISERROR('Disable the trigger prevDrop to drop tables!',11,1);
END
GO
彼らが実装すべきことはINSTEAD OF DDL triggers
- ここで投票してください:
http://connect.microsoft.com/SQLServer/feedback/details/243986
また、ドキュメントを変更してもらいましたが、これはもともと、DDL トリガーがアクションを妨げていると人々を誤解させていましたが、実際にはロールバックされます。
http://connect.microsoft.com/SQLServer/feedback/details/752210
私があなたにこのすべてを伝えている理由は、あなたが次のように述べているからです。
削除しようとしているテーブルを追跡するにはどうすればよいですか?
ただし、これは、テーブルがまだ削除されていないと考えていることを意味します。あります。DDL トリガー内でテーブル名を確実に取得できます。
DECLARE @e XML = EVENTDATA(), @t NVARCHAR(513);
SET @t = @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'nvarchar(255)');
+ '.' + @e.value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(255)');
RAISERROR('%s has been dropped.', 11, 1, @t);
しかし、これは役に立ちません。テーブルが存在しないため、テーブルの内容を確認できません。次のような巧妙なことをしようとしても無駄です。
DECLARE @sql NVARCHAR(MAX) = N'SELECT COUNT(*) FROM ' + @t;
EXEC sp_executesql @sql;
しかし、これは次のようになります。
メッセージ 208、レベル 16、状態 1、行 1
無効なオブジェクト名 'dbo.tablename'。
ただし、トリガーでロールバックするか、トランザクションが中止された場合、テーブルはその後すぐに再び存在します。トリガー自体に関する限り、それは存在しません。