-
Las vistas de INFORMATION_SCHEMA son solo eso:vistas. No puede actualizarlos, por lo que es poco probable que provoquen interbloqueos. Si desea determinar la fuente real (lo que supongo que tiene algo que ver con sus alteraciones u otro código dentro del cursor que no mostró, u otro código que está llamando en combinación con llamar a estos procedimientos, ya que selecciona contra vistas y luego seleccionar variables no puede ser la causa), sugiero leer Publicación de blog de Gail Shaw sobre la interpretación de interbloqueos .
-
A pesar de (1) todavía sugiero usar vistas de catálogo más modernas que INFORMACIÓN_ESQUEMA. La misma información se puede derivar de, por ejemplo, sys.key_constraints.
-
Está utilizando las opciones de cursor predeterminadas; y estás anidando cursores. Si termina usando cursores, debe acostumbrarse a usar un cursor que consuma menos recursos (por ejemplo, LOCAL STATIC FORWARD_ONLY READ_ONLY).
-
En realidad no necesitas un cursor para hacer esto. Así es como volvería a escribir el script de la tabla 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
En cuanto a la secuencia de comandos de creación de índices, creo que hay una mejor manera de hacerlo (nuevamente sin cursores explícitos, no es que evitar el cursor sea el objetivo, pero el código será MUCHO más limpio). Primero necesita una función para construir una clave o incluir columnas del í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
Con esa función en su lugar, un procedimiento de ScriptIndexes es bastante 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
Tenga en cuenta que mi solución no asume que el PK está agrupado (su secuencia de comandos PK codifica CLUSTERED pero luego su secuencia de comandos de índice asume que cualquiera de los índices podría estar agrupado). También ignoro propiedades adicionales, como grupos de archivos, particiones o índices filtrados (de todos modos, no se admiten en 2005).