4

任意のテーブルの挿入コマンドの後に実行されるこのようなストアド プロシージャがあります

Create Procedure [dbo].[HistoryInsert](
@TableName  nVarchar(500),
@RecordId   bigInt
)
As

    declare @Query  nVarChar(max)
    if Not Exists (Select   Top 1 1
                From    Information_schema.tables
                Where   Table_Name  = @TableName + 'History')
        Set @Query  = 'Select  *  Into ' + @TableName + 'History FROM ' + @TableName

    Else
        Set @Query  = 'Insert Into ' + @TableName  + 'History Select *   FROM ' + @TableName
        Exec(@Query)

    Exec(@Query)

この手順を初めて実行すると、履歴テーブルが作成されました。この手順を 2 回目に実行すると、作成されたテーブルに ID 列があるため、挿入に失敗しました。列の ID プロパティをインクリメントせずにすべての列をテーブルから選択する方法。

4

4 に答える 4

7

ライフハックもある

select *
into #tmp_table
from Table

union all

select *
from Table 
where 1<>1

ユニオンをすべて使用すると、SQL Endgine が非推奨になり、制約と ID も継承されます。

      When an existing identity column is selected into a new table, the new column inherits the IDENTITY property, unless one of the following conditions is true:
            - The SELECT statement contains a join, GROUP BY clause, or aggregate function.
            - Multiple SELECT statements are joined by using UNION.
            - The identity column is listed more than one time in the select list.
            - The identity column is part of an expression.
            - The identity column is from a remote data source.
于 2019-08-15T11:54:31.813 に答える
4

あなたのコードは、データ変更の履歴を保持しようとしているように見えます。独自のソリューションを展開する代わりに、変更データ キャプチャの使用を検討してください。

identity指定された列で挿入を許可する 1 つの方法は、 identity_insertです。

SET IDENTITY_INSERT TableName ON

2 番目の exec でこれをオンにすることができます。テーブル全体をコピーしているため、コピーする前に履歴テーブルを一掃する必要があります。たとえば、次を使用しtruncateます。

Set @Query  = 
    'truncate table ' + @TableName  + 'History; ' +
    'set identity_insert ' + @TableName 'History on; ' +
    'Insert Into ' + @TableName  + 'History Select *   FROM ' + @TableName '; ' +
    'set identity_insert ' + @TableName 'History off; '

より適切な解決策は、最初の exec を変更して、identity列のないテーブルを作成することです。私はそれを行うための実用的な方法を見つけていません。SQL Server では、列を削除して再作成する必要があり、非常に面倒な動的 SQL になります。

于 2012-09-22T14:35:24.333 に答える
0

Andomar の言うとおりです。Change Data Captureを使用できるのであれば、そうすべきです。ただし、それをサポートしていないバージョンで立ち往生している場合でも、この問題を回避できます。

マイクロソフトによると...

既存の ID 列が新しいテーブルに選択されると、次の条件のいずれかに該当しない限り、新しい列は IDENTITY プロパティを継承します。

  • SELECT ステートメントに、結合、GROUP BY 句、または集計関数が含まれています。
  • 複数の SELECT ステートメントは、UNION を使用して結合されます。
  • ID 列が選択リストに複数回リストされています。
  • ID 列は式の一部です。
  • ID 列は、リモート データ ソースからのものです。

したがって、たとえば、ID 列の名前がわかっている場合、他の列を知らなくても、次のようなことができます。

Exec('select ' + @identityColName + ' as id_temp123, * into ' + @TableName  + 'History from ' + @TableName)
Exec('alter table ' + @TableName  + ' drop column id_temp123')

これにより、列の順序も保持されます。

情報スキーマを調べることで、ID 列 (存在する場合) をプログラムで見つけることができます。例えば:

select TABLE_NAME + '.' + COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS 
where 
    TABLE_SCHEMA = 'dbo' and 
    TABLE_NAME = 'MyTable' and 
    columnProperty(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
于 2014-10-13T07:07:50.553 に答える