-
As visualizações INFORMATION_SCHEMA são apenas isso - visualizações. Você não pode atualizá-los, portanto, é improvável que causem deadlocks. Se você quiser determinar a fonte real (que eu suponho que tenha algo a ver com seus alters, ou outro código dentro do cursor que você não mostrou, ou outro código que você está chamando em combinação com a chamada desses procedimentos - já que seleciona contra views e, em seguida, selecionar variáveis não pode ser a causa), sugiro ler Post de blog de Gail Shaw sobre interpretação de impasses .
-
Apesar de (1), ainda sugiro usar visualizações de catálogo mais modernas do que INFORMATION_SCHEMA. As mesmas informações podem ser derivadas, por exemplo, de sys.key_constraints.
-
Você está usando as opções padrão do cursor; e você está aninhando cursores. Se você acabar usando cursores, você deve adquirir o hábito de usar um cursor com menos recursos (por exemplo, LOCAL STATIC FORWARD_ONLY READ_ONLY).
-
Na verdade, você não precisa de um cursor para fazer isso. Aqui está como eu reescreveria o script da tabela PK:
CREATE PROCEDURE dbo.ScriptPKForTable @TableName SYSNAME AS BEGIN SET NOCOUNT ON; DECLARE @pkName SYSNAME, @clustered BIT, @object_id INT, @sql NVARCHAR(MAX); SELECT @object_id = OBJECT_ID(UPPER(@TableName)); SELECT @pkName = kc.name, @clustered = CASE i.[type] WHEN 1 THEN 1 ELSE 0 END FROM sys.key_constraints AS kc INNER JOIN sys.indexes AS i ON kc.parent_object_id = i.[object_id] AND kc.unique_index_id = i.index_id WHERE kc.parent_object_id = @object_id AND kc.[type] = 'pk'; SET @sql = N'ALTER TABLE ' + QUOTENAME(@TableName) + ' ADD CONSTRAINT ' + @pkName + ' PRIMARY KEY ' + CASE @clustered WHEN 1 THEN 'CLUSTERED' ELSE '' END + ' ('; SELECT @sql = @sql + c.name + ',' FROM sys.index_columns AS ic INNER JOIN sys.indexes AS i ON ic.index_id = i.index_id AND ic.[object_id] = i.[object_id] INNER JOIN sys.key_constraints AS kc ON i.[object_id] = kc.[parent_object_id] AND kc.unique_index_id = i.index_id INNER JOIN sys.columns AS c ON i.[object_id] = c.[object_id] AND ic.column_id = c.column_id WHERE kc.[type] = 'PK' AND kc.parent_object_id = @object_id ORDER BY key_ordinal; SET @sql = LEFT(@sql, LEN(@sql) - 1) + ');'; SELECT COALESCE(@sql, ' '); END GO
Quanto ao script de criação de índice, acho que há uma maneira melhor de fazer isso (novamente sem cursores explícitos, não que evitar o cursor seja o objetivo, mas o código será MUITO mais limpo). Primeiro, você precisa de uma função para criar uma chave ou incluir colunas do índice:
CREATE FUNCTION dbo.BuildIndexColumns
(
@object_id INT,
@index_id INT,
@included_columns BIT
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @s NVARCHAR(MAX);
SELECT @s = N'';
SELECT @s = @s + c.name + CASE ic.is_descending_key
WHEN 1 THEN ' DESC' ELSE '' END + ','
FROM sys.index_columns AS ic
INNER JOIN sys.columns AS c
ON ic.[object_id] = c.[object_id]
AND ic.column_id = c.column_id
WHERE c.[object_id] = @object_id
AND ic.[object_id] = @object_id
AND ic.index_id = @index_id
AND ic.is_included_column = @included_columns
ORDER BY ic.key_ordinal;
IF @s > N''
SET @s = LEFT(@s, LEN(@s)-1);
RETURN (NULLIF(@s, N''));
END
GO
Com essa função, um procedimento ScriptIndexes é bem fácil:
CREATE PROCEDURE dbo.ScriptIndexesForTable
@TableName SYSNAME
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@sql NVARCHAR(MAX),
@object_id INT;
SELECT @sql = N'', @object_id = OBJECT_ID(UPPER(@TableName));
SELECT @sql = @sql + 'CREATE '
+ CASE i.is_unique WHEN 1 THEN 'UNIQUE ' ELSE '' END
+ CASE i.[type] WHEN 1 THEN 'CLUSTERED ' ELSE '' END
+ ' INDEX ' + i.name + ' ON ' + QUOTENAME(@TableName) + ' ('
+ dbo.BuildIndexColumns(@object_id, i.index_id, 0)
+ ')' + COALESCE(' INCLUDE('
+ dbo.BuildIndexColumns(@object_id, i.index_id, 1)
+ ')', '') + ';' + CHAR(13) + CHAR(10)
FROM
sys.indexes AS i
WHERE
i.[object_id] = @object_id
-- since this will be covered by ScriptPKForTable:
AND i.is_primary_key = 0
ORDER BY i.index_id;
SELECT COALESCE(@sql, ' ');
END
GO
Observe que minha solução não pressupõe que o PK esteja agrupado (seu script PK codifica CLUSTERED, mas seu script de índice assume que qualquer um dos índices pode ser agrupado). Eu também ignoro propriedades adicionais, como grupo de arquivos, particionamento ou índices filtrados (não suportados em 2005 de qualquer maneira).