-
INFORMATION_SCHEMA weergaven zijn precies dat - weergaven. U kunt ze niet bijwerken, dus het is onwaarschijnlijk dat ze een impasse veroorzaken. Als je de echte bron wilt bepalen (waarvan ik aanneem dat het iets te maken heeft met je alters, of andere code binnen de cursor die je niet liet zien, of andere code die je aanroept in combinatie met het aanroepen van deze procedures - aangezien selecteert tegen weergaven en het selecteren van variabelen kan niet de oorzaak zijn), raad ik aan Gail Shaw's blogbericht over het interpreteren van impasses .
-
Ondanks (1) raad ik nog steeds aan om modernere catalogusweergaven te gebruiken dan INFORMATION_SCHEMA. Dezelfde informatie kan bijvoorbeeld worden afgeleid uit sys.key_constraints.
-
U gebruikt de standaard cursoropties; en je nestt cursors. Als je uiteindelijk nog steeds cursors gebruikt, moet je er een gewoonte van maken om een minder resource-intensieve cursor te gebruiken (bijv. LOCAL STATIC FORWARD_ONLY READ_ONLY).
-
Je hebt hiervoor eigenlijk geen cursor nodig. Hier is hoe ik het PK-tabelscript zou herschrijven:
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
Wat betreft het script voor het maken van een index, ik denk dat er een betere manier is om dit te doen (opnieuw zonder expliciete cursors, niet dat het vermijden van de cursor het doel is, maar de code zal VEEL schoner zijn). Eerst heb je een functie nodig om een sleutel te bouwen of kolommen uit de index op te nemen:
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
Met die functie is een ScriptIndexes-procedure vrij eenvoudig:
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
Merk op dat mijn oplossing er niet van uitgaat dat de PK geclusterd is (uw PK-script hardcodes CLUSTERED maar dan gaat uw indexscript ervan uit dat een van de indexen geclusterd zou kunnen zijn). Ik negeer ook extra eigenschappen zoals bestandsgroep, partitionering of gefilterde indexen (in ieder geval niet ondersteund in 2005).