我試圖創建一個服務器範圍的觸發器,以防止壓縮或分區在任何有索引的索引中丟失。現在,它只是在開發中。觸發如下:觸發器返回意外的結果
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