Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Bế tắc khi truy vấn INFORMATION_SCHEMA

  1. 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 .

  2. 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.

  3. 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).

  4. 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).




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách thực thi sp_send_dbmail trong khi giới hạn quyền

  2. IDENT_CURRENT so với @@ IDENTITY so với SCOPE_IDENTITY trong SQL Server:Sự khác biệt là gì?

  3. Tôi có thể thêm một hàm do người dùng xác định ở cấp máy chủ trong SQL Server 2008 r2 không?

  4. Thay đổi hiệu suất thu thập dữ liệu có bị hạn chế đối với các bảng đã bật CDC không?

  5. Không có đủ bộ nhớ hệ thống trong nhóm tài nguyên 'nội bộ'