-
INFORMATION_SCHEMA visninger er netop det - visninger. Du kan ikke opdatere dem, så det er usandsynligt, at de forårsager dødvande. Hvis du vil bestemme den rigtige kilde (som jeg antager har noget at gøre med dine ændringer, eller anden kode i markøren, som du ikke viste, eller anden kode du kalder i kombination med at kalde disse procedurer - da vælger mod visninger og derefter valg af variabler kan ikke være årsagen), foreslår jeg, at du læser Gail Shaws blogindlæg om fortolkning af dødvande .
-
På trods af (1) foreslår jeg stadig at bruge mere moderne katalogvisninger end INFORMATION_SCHEMA. Den samme information kan udledes af f.eks. sys.key_constraints.
-
Du bruger standardmarkørens muligheder; og du indlejrer markører. Hvis du ender med stadig at bruge markører, bør du vænne dig til at bruge en mindre ressourcekrævende markør (f.eks. LOCAL STATIC FORWARD_ONLY READ_ONLY).
-
Du behøver faktisk ikke en markør for at gøre dette. Her er, hvordan jeg ville omskrive PK-tabelscriptet:
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
Med hensyn til indeksoprettelsesscriptet, tror jeg, at der er en bedre måde at gøre dette på (igen uden eksplicitte markører, ikke at det er målet at undgå markøren, men koden vil være MEGET renere). Først skal du bruge en funktion til at bygge enten nøgle eller inkludere kolonner fra indekset:
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
Med den funktion på plads er en ScriptIndex-procedure ret nem:
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
Bemærk, at min løsning ikke antager, at PK er klynget (dit PK-script hard-codes CLUSTERED, men så antager dit indeksscript, at et hvilket som helst af indekserne kan være klynget). Jeg ignorerer også yderligere egenskaber såsom filgruppe, partitionering eller filtrerede indekser (understøttet i hvert fald ikke i 2005).