sql >> Databáze >  >> RDS >> Sqlserver

Zablokování při dotazování INFORMATION_SCHEMA

  1. Zobrazení INFORMATION_SCHEMA jsou právě to - zobrazení. Nemůžete je aktualizovat, takže je nepravděpodobné, že způsobí uváznutí. Pokud chcete určit skutečný zdroj (což předpokládám má něco společného s vašimi změnami nebo jiným kódem v kurzoru, který jste nezobrazili, nebo jiným kódem, který voláte v kombinaci s voláním těchto procedur - protože vybírá proti zobrazení a potom výběr proměnných nemůže být příčinou), doporučuji přečíst Blogový příspěvek Gail Shaw o interpretaci uváznutí .

  2. Navzdory (1) stále doporučuji používat modernější zobrazení katalogu, než je INFORMATION_SCHEMA. Stejné informace lze odvodit například z sys.key_constraints.

  3. Používáte výchozí možnosti kurzoru; a vnořujete kurzory. Pokud nakonec stále používáte kurzory, měli byste si zvyknout používat kurzor méně náročný na zdroje (např. LOCAL STATIC FORWARD_ONLY READ_ONLY).

  4. Ve skutečnosti k tomu nepotřebujete kurzor. Zde je návod, jak bych přepsal skript tabulky 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
    

Pokud jde o skript pro vytváření indexu, myslím, že existuje lepší způsob, jak to udělat (opět bez explicitních kurzorů, ne že by bylo cílem vyhnout se kurzoru, ale kód bude mnohem čistší). Nejprve potřebujete funkci pro sestavení klíče nebo zahrnutí sloupců z indexu:

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

S touto funkcí je postup ScriptIndexes docela snadný:

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

Všimněte si, že moje řešení nepředpokládá, že PK je seskupený (váš skript PK má pevné kódy CLUSTERED, ale pak váš indexový skript předpokládá, že jakýkoli z indexů by mohl být seskupený). Také ignoruji další vlastnosti, jako je skupina souborů, rozdělení nebo filtrované indexy (v roce 2005 stejně nejsou podporovány).




  1. Problémy se změnou data pomocí spouště v orákulu

  2. Postgres:VYBERTE název sloupce na základě booleovské hodnoty

  3. Porovnejte a nechte nová data vložit do tabulky podle měsíce

  4. Jak mohu odkazovat na tabulku cizích klíčů dvakrát?