-
Tampilan INFORMATION_SCHEMA hanya itu - tampilan. Anda tidak dapat memperbaruinya sehingga tidak mungkin menyebabkan kebuntuan. Jika Anda ingin menentukan sumber sebenarnya (yang saya asumsikan ada hubungannya dengan perubahan Anda, atau kode lain di dalam kursor yang tidak Anda tunjukkan, atau kode lain yang Anda panggil dalam kombinasi dengan memanggil prosedur ini - karena memilih melawan dilihat dan kemudian memilih variabel tidak dapat menjadi penyebabnya), saya sarankan membaca Pos blog Gail Shaw tentang menafsirkan kebuntuan .
-
Terlepas dari (1) saya masih menyarankan untuk menggunakan tampilan katalog yang lebih modern daripada INFORMATION_SCHEMA. Informasi yang sama dapat diperoleh dari, misalnya, sys.key_constraints.
-
Anda menggunakan opsi kursor default; dan Anda membuat kursor bersarang. Jika pada akhirnya Anda masih menggunakan kursor, Anda harus membiasakan diri menggunakan kursor dengan sumber daya yang lebih sedikit (mis. LOCAL STATIC FORWARD_ONLY READ_ONLY).
-
Anda sebenarnya tidak memerlukan kursor untuk melakukan ini. Inilah cara saya menulis ulang skrip tabel 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
Adapun skrip pembuatan indeks, saya pikir ada cara yang lebih baik untuk melakukan ini (sekali lagi tanpa kursor eksplisit, bukan berarti menghindari kursor adalah tujuannya, tetapi kodenya akan menjadi BANYAK lebih bersih). Pertama, Anda memerlukan fungsi untuk membuat kunci atau menyertakan kolom dari indeks:
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
Dengan fungsi tersebut, prosedur ScriptIndexes cukup mudah:
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
Perhatikan bahwa solusi saya tidak menganggap PK dikelompokkan (skrip PK Anda hard-code CLUSTERED tetapi kemudian skrip indeks Anda mengasumsikan bahwa salah satu indeks dapat dikelompokkan). Saya juga mengabaikan properti tambahan seperti filegroup, partisi, atau indeks yang difilter (tidak didukung pada tahun 2005).