1

テーブルに行がある場合、テーブルを削除しないようにしたい。

私が書いた:

create trigger prevDrop on database for drop_table
as
begin
   if exists (select * from dropped_table)
    raiserror('cant do',25,1)
end

しかし、で構文エラーが発生しますdropped table

削除しようとしているテーブルを追跡するにはどうすればよいですか?

4

1 に答える 1

2

この場合はアフタートリガーであるため、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'。

ただし、トリガーでロールバックするか、トランザクションが中止された場合、テーブルはその後すぐに再び存在します。トリガー自体に関する限り、それは存在しません。

于 2013-02-06T23:48:51.820 に答える