質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

2863閲覧

SQL 同じレイアウト同士のテーブルでキーが一致するものを更新するにはどうしたらよいでしょうか

emk

総合スコア12

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2018/02/03 03:10

実現したいこと

Aテーブルの一部のレコードが新しく更新されているBテーブルがあるとします。
Bテーブルの内容をAテーブルに反映させるにはどうしたらよいでしょうか。

具体例

tomさんとaaronさんだけを、update_memberの内容で更新したいです。

Aテーブル「member」 カラム id, name, salary

1 | tom | 20 2 | john | 30 3 | aaron | 200

Bテーブル「update_member」 カラム id, name, salary

1 | tom | 18 3 | aaron | 300

SQL

idが同じものだけBの内容をAに反映したいので、以下のように書きました。

sql

1update member a 2set (id, name, salary) = 3 ( 4 select 5 id 6 ,name 7 ,salary 8 from 9 update_member b 10 where 11 a.id = b.id 12 ) 13;

結果

結果は以下のようになりました。

1 | tom | 18 | | 3 | aaron | 300

なって欲しかったのは↓です。

1 | tom | 18 2 | john | 30 3 | aaron | 300

よろしくお願いします。

補足情報

  • 上はpostgresで実行しました。
  • 業務ではOracleですが、MERGEは使わない実装方法が知りたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

上はpostgresで実行しました。

業務ではOracleですが、MERGEは使わない実装方法が知りたいです。

データベースによって方言もありますから、本番と同じデータベース、同じバージョン、同じパッチ環境を用意するのは基本です。

SQLの質問の際は必要な create table, insert も提示できた方が解決が早いです。

SQL

1create table member 2 ( 3 id number(5) 4 , name varchar2(128) 5 , salary number(10) 6 , constraint pk_member primary key(id) using index 7 ) ; 8 9create table update_member 10 ( 11 id number(5) 12 , name varchar2(128) 13 , salary number(10) 14 , constraint pk_update_member primary key(id) using index 15 ) ;

SQL

1insert into member(id, name, salary)values(1, 'tom', 20) ; 2insert into member(id, name, salary) values(2, 'john', 30) ; 3insert into member(id, name, salary) values(3, 'aaron', 200) ; 4 5insert into update_member(id, name, salary) values(1, 'tom', 18) ; 6insert into update_member(id, name, salary) values(3, 'aaron', 300) ; 7commit ;

SQL

1update 2 ( 3 select 4 men.id 5 , men.name 6 , men.salary 7 , um.id as um_id 8 , um.name as um_name 9 , um.salary as um_salary 10 from member men 11 inner join update_member um 12 on men.id = um.id 13 ) a 14set 15 a.name = a.um_name 16 , a.salary = a.um_salary ;

2行が更新されました。

SQL

1select * from member order by id ; 2 ID NAME SALARY 3------------- ---------- ------------- 4 1 tom 18 5 2 john 30 6 3 aaron 300

投稿2018/02/03 08:43

編集2018/02/03 08:45
Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

emk

2018/02/03 09:06

ご回答ありがとうございます。 > データベースによって方言もありますから、本番と同じデータベース、同じバージョン、同じパッチ環境を用意するのは基本です。 手元の環境構築を怠ってしまいました。 > SQLの質問の際は必要な create table, insert も提示できた方が解決が早いです。 たしかにその通りですね!今後そのようにします。アドバイスありがとうございます。
guest

0

updateの方のwhereに

sql

1(select id from update_member where a.id = id) IS NOT NULL

をつけるとどうでしょうか?

投稿2018/02/03 03:22

dala00

総合スコア441

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

emk

2018/02/03 03:53

できました!ありがとうございます。 postgres=# update member a postgres-# set (id, name, salary) = postgres-# ( postgres(# select postgres(# id postgres(# ,name postgres(# ,salary postgres(# from postgres(# update_member b postgres(# where postgres(# a.id = b.id postgres(# ) postgres-# where (select id from update_member where a.id = id) IS NOT NULL postgres-# ; UPDATE 2 postgres=# select * from member order by id; id | name | salary ----+-------+-------- 1 | tom | 18 2 | john | 30 3 | aaron | 300 (3 rows)
guest

0

ベストアンサー

検証環境

macOS High Sierra 10.13.2
PostgreSQL 10.1

準備

create table member(
id varchar(255),
name varchar(255),
salary varchar(255)
);

create table update_member(
id varchar(255),
name varchar(255),
salary varchar(255)
);

-- member
INSERT INTO member(id, name, salary) VALUES('1', 'tom', '20');
INSERT INTO member(id, name, salary) VALUES('2', 'john', '30');
INSERT INTO member(id, name, salary) VALUES('3', 'aaron', '200');

-- update_member
INSERT INTO update_member(id, name, salary) VALUES('1', 'tom', '18');
INSERT INTO update_member(id, name, salary) VALUES('3', 'aaron', '300');

回答

そのSQLだとUPDATE分の条件がないため、全件更新しようとしに行きます、
ですが、更新用の値(サブクエリの結果)にjohnがないため、nullで更新されてしまいます。
UPDATE分のWHERE区に

update_memberに該当するidが存在していること

を更新の条件として指定するとうまく行くと思います。

update member a set (id, name, salary) = ( select id ,name ,salary from update_member b where a.id = b.id ) where exists(select '1' from update_member temp where temp.id = a.id )

手元の本(プログラマのためのSQL)だと相関サブクエリを使ってupdateするならexistsを指定するのが良いそうです
また、相関サブクエリの結果が一行にならないと失敗します。
(update_memberのidに一位制約がついていない場合は危険)

手元で確認したエラー

ERROR: more than one row returned by a subquery used as an expression

投稿2018/02/03 03:52

yuyabu

総合スコア63

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

emk

2018/02/03 04:05

できました!ありがとうございます。 スッキリわかるSQL入門「ほかのテーブルに値が登場する行のみ抽出したい」時にEXISTS演算子が使えるとありました。不勉強でお恥ずかしいです。 postgres=# update member a postgres-# set (id, name, salary) = postgres-# ( postgres(# select postgres(# id postgres(# ,name postgres(# ,salary postgres(# from postgres(# update_member b postgres(# where postgres(# a.id = b.id postgres(# ) postgres-# where exists(select '1' from update_member temp where temp.id = a.id ) postgres-# ; UPDATE 2 postgres=# select * from member order by id; id | name | salary ----+-------+-------- 1 | tom | 18 2 | john | 30 3 | aaron | 300 (3 rows)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問