Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Застой при заявка INFORMATION_SCHEMA

  1. Изгледите на INFORMATION_SCHEMA са точно това - изгледи. Не можете да ги актуализирате, така че е малко вероятно да причинят блокиране. Ако искате да определите истинския източник (което предполагам има нещо общо с вашите промени или друг код в курсора, който не сте показали, или друг код, който извиквате в комбинация с извикването на тези процедури - тъй като избира срещу изгледи и след това избирането на променливи не може да е причината), предлагам да прочетете Публикация в блога на Гейл Шоу за тълкуване на блокирания .

  2. Въпреки (1) все още предлагам да използвате по-модерни каталожни изгледи от INFORMATION_SCHEMA. Същата информация може да бъде извлечена например от sys.key_constraints.

  3. Използвате опциите на курсора по подразбиране; и влагате курсори. Ако в крайна сметка все още използвате курсори, трябва да придобиете навика да използвате курсор с по-малко ресурси (напр. LOCAL STATIC FORWARD_ONLY READ_ONLY).

  4. Всъщност не се нуждаете от курсор, за да направите това. Ето как бих пренаписал скрипта на 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
    

Що се отнася до скрипта за създаване на индекс, мисля, че има по-добър начин да направите това (отново без изрични курсори, не че избягването на курсора е целта, но кодът ще бъде МНОГО по-чист). Първо се нуждаете от функция за изграждане на ключ или за включване на колони от индекса:

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

С тази функция процедурата ScriptIndexes е доста лесна:

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

Обърнете внимание, че моето решение не предполага, че PK е групиран (вашият PK скрипт твърдо кодира CLUSTERED, но след това вашият индексен скрипт приема, че всеки от индексите може да бъде групиран). Също така пренебрегвам допълнителни свойства като файлова група, разделяне или филтрирани индекси (не се поддържат през 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. Разрешение за достъп до sys.dm_db_index_usage_stats

  2. Как да получа броя на редовете от EXEC() в TSQL SPROC?

  3. Какво е логически оператор в SQL Server - SQL Server / TSQL урок, част 123

  4. Преобразуване на низ с израз в десетичен

  5. В паметта OleDbConnection към Excel файл