-
INFORMATION_SCHEMA lượt xem chỉ là - lượt xem. Bạn không thể cập nhật chúng vì vậy chúng không có khả năng gây ra bất kỳ bế tắc nào. Nếu bạn muốn xác định nguồn thực (mà tôi cho rằng có điều gì đó liên quan đến các thay đổi của bạn hoặc mã khác trong con trỏ mà bạn không hiển thị hoặc mã khác bạn đang gọi kết hợp với việc gọi các thủ tục này - vì chọn chống lại xem và sau đó chọn biến không thể là nguyên nhân), tôi khuyên bạn nên đọc Bài đăng trên blog của Gail Shaw về cách giải thích các bế tắc .
-
Mặc dù (1), tôi vẫn khuyên bạn nên sử dụng các chế độ xem danh mục hiện đại hơn INFORMATION_SCHEMA. Thông tin tương tự có thể được lấy từ, ví dụ:sys.key_constraints.
-
Bạn đang sử dụng các tùy chọn con trỏ mặc định; và bạn đang lồng các con trỏ. Nếu cuối cùng bạn vẫn sử dụng con trỏ, bạn nên có thói quen sử dụng con trỏ ít tốn tài nguyên hơn (ví dụ:LOCAL STATIC FORWARD_ONLY READ_ONLY).
-
Bạn thực sự không cần con trỏ để làm điều này. Đây là cách tôi viết lại tập lệnh bảng 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
Đối với kịch bản tạo chỉ mục, tôi nghĩ có một cách tốt hơn để làm điều này (một lần nữa không có con trỏ rõ ràng, không phải là tránh con trỏ là mục tiêu, nhưng mã sẽ trở nên sạch hơn rất nhiều). Trước tiên, bạn cần một hàm để tạo khóa hoặc bao gồm các cột từ chỉ mục:
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
Với chức năng đó, thủ tục ScriptIndexes khá dễ dàng:
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
Lưu ý rằng giải pháp của tôi không giả sử PK được nhóm lại (mã cứng tập lệnh PK của bạn ĐƯỢC ĐIỀU CHỈNH nhưng sau đó tập lệnh chỉ mục của bạn giả định rằng bất kỳ chỉ mục nào có thể được nhóm lại). Tôi cũng bỏ qua các thuộc tính bổ sung như nhóm tệp, phân vùng hoặc chỉ mục được lọc (vẫn chưa được hỗ trợ vào năm 2005).