2016-10-13 17 views
1

Postgres 9.5を使用する。挿入に含まれていないフィールドを挿入選択から戻すことはできますか?

私はいくつかのレコードを持つテーブルbaseを持っている:

CREATE TABLE base 
(
    id serial NOT NULL 
    , thing varchar 
    , copy varchar 
); 

私はテーブルnewにそれらのレコードのサブセットを挿入する:

CREATE TABLE new 
(
    id  serial NOT NULL 
    , new_thing varchar 
    , new_copy varchar 
); 

newは、格納するための列を持っていませんbase.id。しかし、私はnew行がから作成されたことnew.idからbase行にマップできるようにしたいと思います:

CREATE TABLE base_to_new 
(
    base_id int NOT NULL 
    , new_id int NOT NULL 
); 

これは私が何をしたいの要旨であるが、それは動作しません:

WITH new_rows AS 
(
    INSERT INTO new 
    (
    , new_thing 
    , new_copy 
) 

    SELECT 
     thing 
    , copy 

    FROM base 

    WHERE copy = 'yes' 

    RETURNING 
    (
     base.id AS base_id 
    , new.id AS new_id 
) 
) 

INSERT INTO base_to_new 

SELECT 
    new_rows.base_id 
    , new_rows.new_id 

FROM new_rows 
; 

basenewのスキーマは変更できません。

私はまた、実際には のフィールドがテーブルの例よりも多いので、テーブルが非常に大きく、 となりました。ここで

INSERT INTO base_to_new 

SELECT 
    base.id 
    , new.id 

FROM base 

LEFT JOIN new 
    ON thing = new_thing 
    AND item = new_item 
    AND stuff = new_stuff 
    AND last = new_last 
; 

は、スキーマといくつかのデータとSQLのフィドルです:

http://sqlfiddle.com/#!15/bbb9d

ありがとう!

答えて

1

これはbase.thingが一意であると仮定して動作します:

with sel as (
    select * 
    from base 
    where copy = 'yes' 
), 
ins as (
    insert into new (new_thing, new_copy) 
    select thing, copy 
    from sel 
    returning * 
) 
insert into base_to_new 
select sel.id, ins.id 
from sel 
join ins on sel.thing = ins.new_thing; 

ところで、私は本当に厄介としてのモデルが好きではありません。 newbase.idを格納する方が簡単で、より自然です。また、Postgresで独自の意味を持っているので、テーブル名やカラム名にはnewcopyという単語は避けてください。

+0

ありがとうございますが、これで問題は解決しません。最後に私の注釈を見た場合、 'base'からの行が' new'に挿入された行と同じであることを保証するために必要なフィールド比較の数は大きすぎます。さらに、これらの条件に合致する 'new'の行が既にあります。挿入の' base.id'へのアクセスが必要です。 – Sibicle

+0

あなたはより良いデザインでは決して起こらない問題を解決しようとしています。 – klin

+0

私たちは常に理想的なデザインで作業する贅沢さを持っているわけではありません!時には数百の列と数百万行のテーブルを持つレガシーソフトウェアを使用している場合もあります。その解決策を見つけるだけです。とにかくありがとうございます! – Sibicle

関連する問題