-
INFORMATION_SCHEMA vyer är just det - visningar. Du kan inte uppdatera dem så det är osannolikt att de orsakar låsningar. Om du vill bestämma den verkliga källan (som jag antar har något att göra med dina ändringar, eller annan kod i markören som du inte visade, eller annan kod du anropar i kombination med att anropa dessa procedurer - eftersom väljer mot visningar och sedan välja variabler kan inte vara orsaken), föreslår jag att du läser Gail Shaws blogginlägg om tolkning av dödlägen .
-
Trots (1) föreslår jag fortfarande att du använder mer moderna katalogvyer än INFORMATION_SCHEMA. Samma information kan härledas från till exempel sys.key_constraints.
-
Du använder standardmarköralternativen; och du kapar markörer. Om du fortfarande använder markörer bör du ta för vana att använda en mindre resurskrävande markör (t.ex. LOCAL STATIC FORWARD_ONLY READ_ONLY).
-
Du behöver faktiskt ingen markör för att göra detta. Så här skulle jag skriva om PK-tabellskriptet:
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
När det gäller skriptet för att skapa index, tror jag att det finns ett bättre sätt att göra detta (igen utan explicita markörer, inte för att undvika markören är målet, men koden kommer att bli mycket renare). Först behöver du en funktion för att bygga antingen nyckel eller inkludera kolumner från indexet:
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 funktionen på plats är en ScriptIndex-procedur ganska enkel:
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
Observera att min lösning inte förutsätter att PK är klustrat (ditt PK-skript hårdkoder CLUSTERED men sedan antar ditt indexskript att något av indexen kan klustras). Jag ignorerar också ytterligare egenskaper som filgrupp, partitionering eller filtrerade index (stöds inte 2005 i alla fall).