我试图创建一个服务器范围的触发器,以防止压缩或分区在任何有索引的索引中丢失。现在,它只是在开发中。触发如下:触发器返回意外的结果
CREATE TRIGGER [dbtrg_PREVENT_COMPRESSED_PARTITION_LOSS_ON_INDEXES] ON ALL SERVER
AFTER DDL_EVENTS
AS
SET NOCOUNT ON;
CREATE TABLE #t
(
ServerName sysname,
DatabaseName sysname,
TableName sysname,
IndexName sysname,
PartitionNumber INT,
CompressionType NVARCHAR(60)
);
DECLARE @dbName sysname;
DECLARE @dbCursor CURSOR;
DECLARE @sql NVARCHAR(MAX);
SET
@dbCursor = CURSOR
FOR SELECT name
FROM sys.databases
WHERE source_database_id IS NULL
AND database_id > 4
AND NAME <> 'AdventureWorks2008R2'
AND is_read_only = 0
AND state_desc = 'ONLINE'
ORDER BY name;
OPEN @dbCursor;
FETCH NEXT FROM @dbCursor INTO @dbName;
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET @sql = 'USE [' + @dbName + ' ]
INSERT INTO #t
SELECT @@SERVERNAME AS ServerName,
DB_NAME() AS DatabaseName,
st.name AS TableName,
si.name AS IndexName,
sp.partition_number AS PartitionNumber,
sp.data_compression_desc AS CompressionType
FROM sys.partitions SP WITH (NOLOCK)
LEFT JOIN sys.tables ST WITH (NOLOCK) ON st.object_id = sp.object_id
LEFT OUTER JOIN sys.indexes SI WITH (NOLOCK) ON sp.object_id = si.object_id
AND sp.index_id = si.index_id
AND st.object_id = si.object_id
WHERE st.type = ''U''
AND data_compression <> 0
ORDER BY st.name, si.index_id, si.name, sp.partition_number';
EXECUTE sp_executesql @sql;
FETCH NEXT FROM @dbCursor INTO @dbName;
END;
CLOSE @dbCursor;
DEALLOCATE @dbCursor;
DECLARE @xmlEventData XML = EVENTDATA();;
DECLARE @IndexName VARCHAR(100) = (SELECT IndexName FROM #t)
DECLARE @QueryBody VARCHAR(MAX) = (SELECT CONVERT(VARCHAR(MAX), @xmlEventData.query('data(/EVENT_INSTANCE/TSQLCommand/CommandText)')))
DECLARE @eventType SYSNAME = @xmlEventData.value('(/EVENT_INSTANCE/EventType)[1]','nvarchar(128)');
IF (@eventType IN ('ALTER INDEX', 'CREATE INDEX', 'DROP INDEX'))
BEGIN
IF (@QueryBody LIKE '%' + @IndexName + '%') AND NOT ((@QueryBody LIKE '%REORG%') OR (@QueryBody LIKE '%REBUILD%')) OR NOT (@QueryBody LIKE '%PAGE_COMPRESSION%')
ROLLBACK;
RAISERROR ('This index is either partitioned, compressed, or both. Please see the DBAs to update this index', 16, 1) WITH LOG;
RETURN;
END;
ENABLE TRIGGER [dbtrg_PREVENT_COMPRESSED_PARTITION_LOSS_ON_INDEXES] ON ALL SERVER
GO
当我尝试通过增加一个包含列的索引和取页面压缩掉,以测试它,我得到如下:(旁注:你可能会问我为什么要做到这一点,出于某种未知的原因,这是在生产中使用GUI发生的,我们希望确保它在将来不会发生)。
/*------------------------
USE [AdventureWorks2012]
GO
CREATE UNIQUE NONCLUSTERED INDEX [AK_SalesOrderDetail_rowguid] ON [Sales].[SalesOrderDetail]
(
[rowguid] ASC
)
INCLUDE ( [SalesOrderID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = ON, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
------------------------*/
Msg 512, Level 16, State 1, Procedure dbtrg_PREVENT_COMPRESSED_PARTITION_LOSS_ON_INDEXES, Line 78
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
这当然不是我指定的错误。任何人都可以告诉我我要去哪里吗?
DECLARE @IndexName VARCHAR(100)=(SELECT INDEXNAME FROM #T)很肯定这select返回多行,这是在错误来自。无论如何,它将是该部分的4个声明之一。 –
谢谢!你对此绝对正确。 – PMooney