10

SQL Server 2008 に状況があります。

列の型を変更する必要がありますが、インデックスが変更を妨げています。しかし、データベースが複数のクライアント上にあるため、列に関連するインデックスがいくつ存在するかわかりません。

プログラムで言えば、列を含むすべてのインデックスを取得して削除し、alter tableステートメントの後にそれらを自動的に再作成する方法はありますか?

それらを無効にすると、型の変更によりテーブルが混乱する可能性があると聞きました。

tinyint から smallint 型に変更しています。

4

7 に答える 7

5

宛先テーブルのすべてのインデックスを無効にする

  ALTER INDEX Indexname ON Table DISABLE

次に、列のデータ型を変更します

ALTER TABLE table
ALTER COLUMN columnname datatype

その後、インデックスを有効にします

ALTER INDEX Indexname ON Table REBUILD
于 2013-07-05T12:27:09.423 に答える
2

組み込みツールを使用して、この作業を行うことができます。SQL Server Management Studio で、[ツール]、[オプション] の順にクリックします。

「SQL Server オブジェクト エクスプローラー」セットを展開し、その中で「スクリプト」をクリックします。

右側の [テーブルとビューのオプション] までスクロールします。

"Script Indexes" というレコードを見つけて "True" に設定し、[OK] をクリックします。

オブジェクト エクスプローラーでテーブルを右クリックすると、"スクリプトとして..." のオプションが表示され、これらのオプションのいずれかを選択すると、テーブル自体とそのキーだけでなく、インデックスもスクリプト化されます。必要なスクリプトをコピーするか、必要に応じてすべてを実行します。

于 2017-04-04T15:57:15.823 に答える
0

Microsoft SQL Server インデックスを削除/作成/無効化/有効化 (再構築) するために私が思いついたのは次のとおりです。

CREATE VIEW dbo.vw_INDEX_TEXT AS
  SELECT
    x.[owner_name],
    x.[table_name],
    x.[index_name],
    
    /*
    ** DROP index
    */
    drop_sql = 'DROP INDEX ' + x.[index_name] + ' ON ' + x.[owner_name] + '.' + x.[table_name] + ';',

    
    /*
    ** CREATE index
    */
    create_sql = 
     'CREATE NONCLUSTERED INDEX ' + x.[index_name] + '
        ON ' + x.[owner_name] + '.' + x.[table_name] + '(' + 
          -- the common-delimited field list. 
         substring(
                (SELECT
                  ',' + [field_name] 
                FROM
                  (
                  SELECT 
                    [owner_name] = SCHEMA_NAME(O.schema_id),
                    [table_name] = O.name,
                    [index_name] = I.name,
                    [field_name] = C.name,
                    O.type,
                    S.key_ordinal,
                    S.is_descending_key,
                    S.is_included_column 
                  FROM 
                    sys.all_objects O inner join sys.indexes I       ON (O.object_id = I.object_id )
                                      inner join sys.index_columns S ON (O.object_id = S.object_id and I.index_id=S.index_id)
                                      inner join sys.columns C       ON (O.object_id = C.object_id and S.column_id = C.column_id)
                  WHERE 
                    I.index_id > 0 
                    AND SCHEMA_NAME(O.schema_id) = x.[owner_name] -- N'dbo' 
                    AND I.name                   = x.[index_name] -- the index name N'IDX_myindex' 
                    AND O.name                   = x.[table_name] -- the base table name N'mytable' 
                    AND O.type                   <> 'IT' 
                    AND I.is_primary_key         = 0 -- we are not creating primary keys  
                    AND I.is_unique_constraint   = 0 -- we are not creating unique constraints
                    AND (INDEXPROPERTY(I.object_id,I.name,'IsStatistics') <> 1)
                    AND (INDEXPROPERTY(I.object_id,I.name,'IsAutoStatistics') <> 1) 
                    AND (INDEXPROPERTY(I.object_id,I.name,'IsHypothetical') <> 1) 
                  ) as f
                FOR XML PATH('') 
            ), 2, 8000) -- we trim the leading comma 
            -- end of field list
        + ') 
     WITH (
          PAD_INDEX = OFF
         );',
         
    /*
    ** DISABLE index
    */
    disable_sql = 'ALTER INDEX ' + x.[index_name] + ' ON ' + x.[owner_name] + '.' + x.[table_name] + ' DISABLE;',

    /*
    ** ENABLE (REBUILD) index
    */
    enable_sql = 'ALTER INDEX ' + x.[index_name] + ' ON ' + x.[owner_name] + '.' + x.[table_name] + ' REBUILD;'

         
  FROM
    (SELECT 
      [owner_name] = SCHEMA_NAME(O.schema_id),
      [table_name] = O.name,
      [index_name] = I.name
      -- other interesting, but not used fields that might be useful for other index types:
      -- O.type,I.index_id,I.is_unique,
      -- prop= INDEXPROPERTY(I.object_id,I.name,'IsClustered'),
      -- I.is_padded,
      -- I.fill_factor,
      -- I.ignore_dup_key,I.allow_row_locks,I.allow_page_locks,I.is_disabled,I.data_space_id 
    FROM 
      sys.all_objects O INNER JOIN sys.indexes I on O.object_id=I.object_id 
    WHERE 
      I.index_id>0 
      -- AND O.name = @target_table_name
      AND O.type <> 'IT' 
      AND INDEXPROPERTY(I.object_id,I.name,'IsStatistics')     <> 1 
      AND INDEXPROPERTY(I.object_id,I.name,'IsAutoStatistics') <> 1 
      AND INDEXPROPERTY(I.object_id,I.name,'IsHypothetical')   <> 1 
      AND I.is_primary_key = 0 
      AND I.is_unique_constraint = 0  
    ) as x

最も基本的なインデックスのみが再作成されますが、必要に応じてより複雑なインデックスを作成するための基礎として役立ついくつかの追加フィールドを残しました。

コマンドはビューの各フィールドにあります。execを使用して、実際に次のような操作を実行します ( のテーブル名を入力します@target_table_name)。

  Declare @target_table_name as sysname = 'mytable';
  Declare @sql_cmd           as table(ID int identity, cmd varchar(max) );
  Declare @this_cmd          as varchar(max) = '';
  Declare @ct                as int = 0;
  
  -- populate a temp table to store the results
  INSERT INTO @sql_cmd(cmd)
    SELECT
      cmd = enable_sql
    FROM
      dbo.vw_INDEX_TEXT 
    WHERE 
      table_name = @target_table_name
 
  -- the ID column will help us step though the rows one at a time
  SELECT @ct = max(ID) FROM @sql_cmd

  -- loop over all rows in the table, finding each individual command
  While (@ct > 0) Begin
    SELECT
      @this_cmd = cmd
    FROM
      @sql_cmd
    WHERE
      id = @ct
      
    select @this_cmd

    -- un-comment this line to actually run the command:
    -- exec (@this_cmd)
    
    SET @ct = @ct - 1
  End
    

execこの例では が無効になっていることに注意してください。

于 2021-05-10T16:48:11.947 に答える
0

基本的なケース (列が制約の一部ではなく、XML インデックスを持つ XML 列ではないなど) を想定すると、次のことが可能になります。

  • を使用してインデックスの説明を XML として生成するselect (...) from <sys.indexes + other sys schema views> FOR XML ...
  • 各 XML を、テーブルの拡張プロパティとして名前を付けます。たとえば、プレフィックス「IX_」(「IX_1」、「IX_2」など) を付けます。
  • インデックスを削除
  • 列の変更
  • プレフィックス「IX_」を持つテーブルのすべての拡張プロパティを収集します
  • XML 記述に基づいて各インデックスを再作成する
于 2013-07-05T13:09:09.307 に答える