web-dev-qa-db-ja.com

SQL:特定の列なしで、1つのテーブルから別のテーブルにすべてのレコードを挿入します

特定の列を指定せずに、バックアップテーブルfoo_bkのすべてのレコードをfooテーブルに挿入したいと思います。

このクエリを試すと

INSERT INTO foo 
SELECT *
FROM foo_bk

「挿入エラー:列名または指定された値の数がテーブル定義と一致しません。」というエラーが表示されます。

列名を指定せずに、あるテーブルから別のテーブルに一括挿入を行うことはできますか?私はそれをグーグルしましたが、答えを見つけることができないようです。すべての回答には特定の列が必要です。

11
Jack

あなたはこれをしたくないでしょう。列が移動して挿入が壊れる可能性があるので、select *を挿入の基礎として使用しないでください(さらに悪いことに、挿入を壊さないでデータを台無しにしてください。誰かがselectのテーブルに列を追加したが、他のテーブルを使用すると、コードが壊れます。または、誰かが理解を上回るが頻繁に発生する理由により、テーブルでドロップして再作成し、列を別の順序に移動するとします。これで、last_nameは、first_nameがあった場所です元々、select *は他のテーブルの間違った列に配置します。列の指定、および1つの列から目的のテーブルの目的の列への特定のマッピングに失敗することは、非常に悪い習慣です。

現在、いくつかの問題が発生している可能性があります。最初に2つの構造が直接一致しないか、2番目に挿入されるテーブルにID列があるため、挿入可能な列が直接一致する場合でも、挿入されるテーブルには1つ以上の列がありますもう1つは、データベースを指定しないことで、その列に挿入しようとすることを想定しています。または、列の数は同じでも、1つはIDであるために挿入できない場合があります(ただし、これは別のエラーメッセージになると思います)。

17
HLGEM

この別の投稿: aのすべての値を挿入... 、次のことができます:

INSERT INTO new_table (Foo, Bar, Fizz, Buzz)
SELECT Foo, Bar, Fizz, Buzz
FROM initial_table

他の回答で示されているように列名を指定することが重要です。

11
ragamufin

これを使って

SELECT *
INTO new_table_name
FROM current_table_name
10
nitinuniyal

少なくとも同じ数の列が必要で、各列はまったく同じ方法で定義する必要があります。つまり、varchar列をint列に挿入することはできません。

一括転送については、使用しているSQL実装のドキュメントを確認してください。多くの場合、あるテーブルから別のテーブルにデータを一括転送するために利用できるツールがあります。たとえば、SqlServer 2005の場合、SQL Serverインポートおよびエクスポートウィザードを使用できます。データを移動するデータベースを右クリックし、[エクスポート]をクリックしてアクセスします。

2
Michael Todd

SQL 2008では、INSERT INTO/SELECTではなくSELECT INTOを使用する場合、SELECTでの列名の指定を省略できます。

SELECT *
INTO Foo
FROM Bar
WHERE x=y

INTO句はSQL Server 2000-2005には存在しますが、列名を指定する必要があります。 2008では、SELECT *を使用する機能が追加されたようです。

詳細については、INTO( SQL2005 )、( SQL2008 )に関するMSDNの記事を参照してください。

ただし、INTO句は、宛先テーブルがまだ存在しない場合にのみ機能します。既存のテーブルにレコードを追加する場合、これは役に立ちません。

1
Skeolan

上記のすべての回答は、何らかの理由でSQL Server 2012では機能しませんでした。私の状況では、1行だけでなくすべての行を誤って削除してしまいました。 DBAがテーブルをdbo.foo_bakに復元した後、以下を使用して復元しました。 注:これは、バックアップテーブル(dbo.foo_bakで表される)と書き込み先のテーブル(dbo.foo)がまったく同じ列名を持っている場合にのみ機能します。

これは、さまざまな答えを組み合わせて使用​​した場合にうまくいきました。

USE [database_name];
GO
SET IDENTITY_INSERT dbo.foo ON;
GO
INSERT INTO [dbo].[foo]
           ([rown0]
           ,[row1]
           ,[row2]
           ,[row3]
           ,...
           ,[rown])
     SELECT * FROM [dbo].[foo_bak];
GO
SET IDENTITY_INSERT dbo.foo OFF;
GO

このバージョンの私の回答は、主キーと外部キーがある場合に役立ちます。

1
iamdoubz

おそらく以前の答えから理解したように、あなたは自分が求めていることを実際に行うことはできません。追加/不足している列をマップする方法がわからない場合にSQL Serverで発生する問題を理解できると思います。

とはいえ、ここでの目的はバックアップであるとおっしゃっていたので、SQL Serverを使用して問題を回避できるかもしれません。あなたの正確なシナリオを知らないと、ここで正しい答えを見つけることは不可能になりますが、私は以下を想定しています:

  • テーブルのバックアップ/監査プロセスを管理したい。
  • おそらくそれらがいくつかあり、すべての列の追加/削除で依存オブジェクトを変更しないようにしたいと考えています。
  • バックアップテーブルには、監査目的で追加の列が含まれる場合があります。

私はあなたに2つのオプションを提案したいと思います:

の 効率的な練習 (IMO)これは、DDLトリガーを使用してスキーマの変更を検出し、それに応じてバックアップテーブルを変更するために使用できます。これにより、「select * from ...」アプローチを使用できるようになります。これは、列リストが2つのテーブル間で一貫しているためです。

私はこのアプローチをうまく使用しました。DDLトリガーに監査テーブルを自動的に管理させるために、このアプローチを活用できます。私の場合、監査を必要とするテーブルに命名規則を使用し、DDLトリガーがその場で管理しました。

別のオプション 特定のシナリオに役立つ可能性があるのは、列リストを調整するテーブルのサポートビューを作成することです。ここに簡単な例があります:

create table foo (id int, name varchar(50))
create table foo_bk (id int, name varchar(50), tagid int)
go

create view vw_foo as select id,name from foo 
go

create view vw_foo_bk as select id,name from foo_bk
go

insert into vw_foo
    select * from vw_foo_bk 
go

drop view vw_foo
drop view vw_foo_bk
drop table foo
drop table foo_bk
go

これが役に立てば幸いです:)

0
itayw