SQLテーブルのレコードをどのようにコピーしますが、新しい行の一意のIDを交換しますか?


123

この質問は私が必要としているものに近くなりますが、私のシナリオは少し異なります。ソーステーブルと宛先テーブルは同じで、主キーは一意の識別子(GUID)です。私がこれを試すとき:

insert into MyTable
    select * from MyTable where uniqueId = @Id;

主キーをコピーしようとしているため、明らかに主キー制約違反が発生します。実際には、主キーをまったくコピーしたくありません。むしろ新しいものを作りたい。さらに、特定のフィールドを選択的にコピーし、他のフィールドはnullのままにしておきます。さらに複雑なことに、元のレコードの主キーを取得して、コピーの別のフィールド(PreviousIdフィールド)に挿入する必要があります。

これには簡単な解決策があると確信していますが、それが何であるかを知るのに十分なTSQLを知りません。

回答:


186

これを試して:


insert into MyTable(field1, field2, id_backup)
    select field1, field2, uniqueId from MyTable where uniqueId = @Id;

指定されていないフィールドは、デフォルト値(定義されていない場合は通常NULL)を受け取ります。


2
驚くばかり。魅力のように働いた。あなたがそれを書いたならば、それはとても明白でした。ありがとう!!
キルホーファー

1
これは、列が少ない場合に機能します。20または30列と言っても、この方法を使用することはできますが、困難な作業になります。また、列を追加し、そのデータもコピーしたい場合は、毎回このスクリプトに列を追加する必要があります。最善の方法は、sysテーブルを使用して動的に挿入を生成することです。
ジェヤラ

93

わかりました、古い問題であることはわかっていますが、とにかく回答を投稿します。

私はこのソリューションが好きです。ID列を指定するだけです。

SELECT * INTO TempTable FROM MyTable_T WHERE id = 1;
ALTER TABLE TempTable DROP COLUMN id;
INSERT INTO MyTable_T SELECT * FROM TempTable;
DROP TABLE TempTable;

「id」列はID列であり、指定する必要があるのはそれだけです。とにかく、他の方法よりも優れています。:-)

SQL Serverを使用しています。1と2の行で「CREATE TABLE」と「UPDATE TABLE」を使用することをお勧めします。うーん、私は彼が望んでいた答えを実際には与えなかったことがわかりました。また、IDを別の列にコピーしたいと考えていました。しかし、このソリューションは、新しいauto-idでコピーを作成するのに適しています。

Michael Dibbetsのアイデアを使ってソリューションを編集します。

use MyDatabase; 
SELECT * INTO #TempTable FROM [MyTable] WHERE [IndexField] = :id;
ALTER TABLE #TempTable DROP COLUMN [IndexField]; 
INSERT INTO [MyTable] SELECT * FROM #TempTable; 
DROP TABLE #TempTable;

「、」で区切ると、複数の列を削除できます。:idは、コピーする行のIDに置き換える必要があります。MyDatabase、MyTable、IndexFieldは(もちろん)名前に置き換えてください。


1
これはトリッキーですが、3行目のINSERT INTO中に正しいIDを正しい行にコピーしていることをどのように確認できますか?
エルノ2013

id-columnは(テーブル内の)ID列なので、値は気にしません。「古い」レコードと同じ値を保持する新しいレコードが欲しいだけです。
ジョナス

9
の場合TempTable、を使用した方がいいのではないでしょう#TempTableか。
Jess

3
私はこれを次の形式で使用しています。use MyDatabase; SELECT * INTO #TempTable FROM [TABLE] WHERE [indexfield] = :id; ALTER TABLE #TempTable DROP COLUMN [indexfield]; INSERT INTO [TABLE] SELECT * FROM #TempTable; DROP TABLE #TempTable;この方法で、断続的なファイルをディスクに書き込むことによる遅延なしに、できるだけ早くクリーンアップされることがわかります。
Tschallacka

3
$identityID列名をハードコーディングしたくない場合にも使用できます
Factor Mystic

12

すべての列名を書き出さないようにしようとしていると思います。SQL Management Studioを使用している場合は、テーブルを右クリックして[挿入としてスクリプト]を簡単に実行できます。その後、その出力をいじってクエリを作成できます。


10

IDフィールド以外のすべてのフィールドを指定します。

INSERT INTO MyTable (FIELD2, FIELD3, ..., FIELD529, PreviousId)
SELECT FIELD2, NULL, ..., FIELD529, FIELD1
FROM MyTable
WHERE FIELD1 = @Id;

6

同じ問題があり、他の開発者が定期的に列を追加したテーブルを単一のスクリプトで機能させる必要があります。それだけでなく、お客様が現在のバージョンでは最新でない可能性があるため、私はデータベースのさまざまなバージョンをサポートしています。

私はジョナスによって解決策を取り、少し修正しました。これにより、行のコピーを作成し、元のソーステーブルに追加する前に主キーを変更できます。これは、列にNULL値を許可せず、INSERTで各列名を指定する必要がないテーブルを操作する場合にも非常に便利です。

このコードは「ABC」の行を「XYZ」にコピーします

SELECT * INTO #TempRow FROM SourceTable WHERE KeyColumn = 'ABC';
UPDATE #TempRow SET KeyColumn = 'XYZ';
INSERT INTO SourceTable SELECT * FROM #TempRow;
DELETE #TempRow;

ドロップが終了したら、一時テーブルを削除します。

DROP TABLE #TempRow;

4

私の答えがパーティーに遅れるのはわかっています。しかし、私が解決した方法はすべての答えとは少し異なります。

いくつかの列を除いて、テーブルの行を複製する必要がありました。それらのいくつかは新しい価値を持つでしょう。このプロセスは、テーブルへの将来の変更を自動的にサポートする必要があります。つまり、列名を指定せずにレコードを複製します。

私のアプローチは、

  1. Sys.Columnsをクエリして、テーブルの列の完全なリストを取得し、スキップする列の名前をwhere句に含めます。
  2. それを列名としてCSVに変換します。
  3. ビルド選択...これに基づいてスクリプトに挿入します。


declare @columnsToCopyValues varchar(max), @query varchar(max)
SET @columnsToCopyValues = ''

--Get all the columns execpt Identity columns and Other columns to be excluded. Say IndentityColumn, Column1, Column2 Select @columnsToCopyValues = @columnsToCopyValues + [name] + ', ' from sys.columns c where c.object_id = OBJECT_ID('YourTableName') and name not in ('IndentityColumn','Column1','Column2') Select @columnsToCopyValues = SUBSTRING(@columnsToCopyValues, 0, LEN(@columnsToCopyValues)) print @columnsToCopyValues

Select @query = CONCAT('insert into YourTableName (',@columnsToCopyValues,', Column1, Column2) select ', @columnsToCopyValues, ',''Value1'',''Value2'',', ' from YourTableName where IndentityColumn =''' , @searchVariable,'''')

print @query exec (@query)



1

「キー」があなたのPKフィールドであり、それが自動数値の場合。

insert into MyTable (field1, field2, field3, parentkey)
select field1, field2, null, key from MyTable where uniqueId = @Id

新しいレコードを生成し、元のレコードからfield1とfield2をコピーします


1

テーブルには100個のフィールドがあり、機能するためにはクエリが必要でした。これで、いくつかの基本的な条件付きロジックを使用して任意の数のフィールドを切り替えることができ、その序数の位置を気にする必要はありません。

  1. 以下のテーブル名を自分のテーブル名に置き換えます

    SQLcolums = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE (TABLE_NAME = 'TABLE-NAME')"
    
    Set GetColumns = Conn.Execute(SQLcolums)
    Do WHILE not GetColumns.eof
    
    colName = GetColumns("COLUMN_NAME")
  2. 元のIDフィールド名をPKフィールド名に置き換えます

    IF colName = "ORIGINAL-IDENTITY-FIELD-NAME" THEN ' ASSUMING THAT YOUR PRIMARY KEY IS THE FIRST FIELD DONT WORRY ABOUT COMMAS AND SPACES
        columnListSOURCE = colName 
        columnListTARGET = "[PreviousId field name]"
    ELSE
        columnListSOURCE = columnListSOURCE & colName
        columnListTARGET = columnListTARGET & colName
    END IF
    
    GetColumns.movenext
    
    loop
    
    GetColumns.close    
  3. テーブル名を再度置き換えます(ターゲットテーブル名とソーステーブル名の両方)。where条件を編集する

    SQL = "INSERT INTO TARGET-TABLE-NAME (" & columnListTARGET & ") SELECT " & columnListSOURCE & " FROM SOURCE-TABLE-NAME WHERE (FIELDNAME = FIELDVALUE)" 
    Conn.Execute(SQL)

0

あなたはこのようにすることができます:

INSERT INTO DENI/FRIEN01P 
SELECT 
   RCRDID+112,
   PROFESION,
   NAME,
   SURNAME,
   AGE, 
   RCRDTYP, 
   RCRDLCU, 
   RCRDLCT, 
   RCRDLCD 
FROM 
   FRIEN01P      

そこで、112の代わりに、テーブルDENI / FRIEN01Pに最大IDの数を入力する必要があります。


0

ここでは、ASPクラシックを使用してそれを実行した方法を示しますが、上記の回答でうまく機能することができず、システム内の製品を新しいproduct_idにコピーできるようにしたかったのです。テーブルに列を追加します。

Cn.Execute("CREATE TEMPORARY TABLE temprow AS SELECT * FROM product WHERE product_id = '12345'")
Cn.Execute("UPDATE temprow SET product_id = '34567'")
Cn.Execute("INSERT INTO product SELECT * FROM temprow")
Cn.Execute("DELETE temprow")
Cn.Execute("DROP TABLE temprow")

これを完了するために5つの個別のSQLコマンドを発行する必要があるとは思いません。また、2番目のコマンドで誰が製品IDを34567にすべきかを決定しますか
ジェヤラ

34567は一例です。変数または必要なものに設定できます。ASPクラシックでこれを行うより良い方法がある場合は、お知らせください。:)
Daniel Nordh

これらすべてを1行で実行するストアドプロシージャを作成できます。また、通常、PKは自動インクリメント値でした。したがって、自分に割り当てることはお勧めできません。
ジェヤラ

この手順をどのように記述しますか?教えてください。PK?商品IDを意味する場合、システムでは、販売先の店舗に基づいて商品IDを使用します。たとえば、おもちゃ屋はすべて30から始まる商品番号があり、スポーツ店は60から始まります。さらに、スペースを節約して、たとえば、同じ種類の他のものの隣に記事IDを置くことができます。言ったように、これは私たちのシステムで機能する私のソリューションでした。変数の設定方法はそれほど重要ではなく、ほとんどのプログラマーは変数とそのシステムで何が機能するかを理解します。
Daniel Nordh

PKは主キーの略です。あなたの場合、その「12345」です。方法がわからない場合に、Classic ASPでストアドプロシージャを使用する方法については、stackoverflow.com / questions / 21561657 / …を参照してください。これを行うには、これらすべてを1つのストアドプロシージャに移動し、 '12345'をパラメーターとして渡します。あなたのやり方は機能しますが、最近はパラメーター化されたスクリプトが推奨されています。
ジェヤラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.