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

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

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

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

1回答

1609閲覧

Postgresで別テーブルをJOINしてUPDATEしたい

hello_whats_up

総合スコア57

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

0クリップ

投稿2020/06/10 06:57

編集2020/06/10 09:46

解決したいこと

GoのMasterminds/squirrelをつかって開発をしています。
Updateをする際に、他のテーブルをJoinしてそこのデータからWhereで条件をつけたいと考えています。
PostgresではUpdateの際のJoinが使えないということで以下のようなSQLをsquirrelで実現したいです。

SQL

1UPDATE table1 SET column = value 2FROM table2 3WHERE table1.column2 = table2.column2

また、現在の私のコードはこのような状態です。
Whereの部分を変更して別テーブルの値を条件にしたいと思っています。

SQLと同様の形でquirrelでも書いてみたのですがUnreference等のエラーが出てしまいます。
(↓のコード中ではFromが使用できないため。UpdateBuilderではFromは定義されていない)
何か分かられる方はご教示お願いします。

Go

1query, args, err := (sq.StatementBuilder.PlaceholderFormat(sq.Dollar). 2 Update(`"user"`). 3 SetMap(data). 4 Where(sq.Eq{`"user_id"`: 10}). 5 ToSql() 6 if err != nil { 7 return err 8 } 9 r, err := tx.Exec(query, args...) 10 if err != nil { 11 return err 12 } 13 if err := p.exec(r, 1); err != nil { 14 return err 15 } 16 return nil

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

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

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

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

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

guest

回答1

0

ベストアンサー

Masterminds/squirrel のライブラリでシンプルに以下のクエリを生成するのは難しいかと思います。

UPDATE table1 SET column = value
FROM table2
WHERE table1.column2 = table2.column2

なぜなら Update するときのビルダー UpdateBuilder に対して FROM 句を指定できるメソッドがないためです。

https://godoc.org/github.com/Masterminds/squirrel#UpdateBuilder を参照

別の方法として EXISTS 句を用いて絞り込む方法があります。以下は EXISTS を用いて同様の絞り込みができるクエリの例です。EXISTS の条件などはよしなにクエリパラメータで指定できるようにすれば良さそうです。
(まぁでもちょっと複雑なクエリを発行したい場合、個人的には素の SQL を書きたいですね...)

  • Masterminds/squirrel を用いたビルダー実装

go

1package main 2 3import ( 4 "fmt" 5 6 sq "github.com/Masterminds/squirrel" 7) 8 9func main() { 10 nestedBuilder := sq.StatementBuilder.PlaceholderFormat(sq.Dollar).Select("x").Prefix("EXISTS ("). 11 From("table1").Join("table2 ON table1.column2 = table2.column2").Suffix(")") 12 13 outerSql, _, _ := sq.StatementBuilder.PlaceholderFormat(sq.Dollar).Update("table1"). 14 Set("column", "hoge"). 15 Where(nestedBuilder).ToSql() 16 17 fmt.Println(outerSql) 18}
  • 出力結果
UPDATE table1 SET column = $1 WHERE EXISTS ( SELECT x FROM table1 JOIN table2 ON table1.column2 = table2.column2 )

投稿2020/06/10 12:36

編集2020/06/10 13:23
d_tutuz

総合スコア730

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

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

hello_whats_up

2020/06/10 14:29

いつもありがとうございます。 おかげさまでに所望の結果を得ることができました! ただ、あと一つ追加でしたいことがあります。 Updateするカラムの条件として、 Where("table1"."id" = 変数)というものを追加したいのですが、 missing FROM-clause entry for table \"table1\" というエラーに悩まされています。解決策がお分かりでしたら教えていただけると幸いです。
d_tutuz

2020/06/11 00:09

outerの行を以下のように変えればいけると思いますよ outerSql, _, _ := sq.StatementBuilder.PlaceholderFormat(sq.Dollar).Update("table1"). Set("column", "hoge"). Where(nestedBuilder).Where("table1.id = ?", "111").ToSql()
d_tutuz

2020/06/11 00:51

余談ですが、ライブラリの使い方を知る方法として"テスト"のコードを見てみる、という方法があります。 Masterminds/squirrel にあるテストのコードをみるとライブラリの使い方と、そのライブラリを使用したときに出力できる期待するSQLの例がいろいろ記載されています。(単体テストなので当たり前といえば当たり前ですが) GoDoc だけではわかりにくいこともあると思うので、実際にライブラリのソースコードをローカルに git clone してテストケースのコードを読んでみるのも、使い方を知る一つの方法だったりします。ご参考までに。
hello_whats_up

2020/06/11 03:08

ありがとうございます!使い方の方法、参考にさせていただきます。 すみません、間違えていました.. Where("table2"."id" = 変数)のようにJoinしたテーブルの値を参照したいときに、上記のようなエラーが出てしまいます。 この場合の対処法をお聞きしたかったです。
d_tutuz

2020/06/11 03:46

EXISTS 句が含まれるサブクエリ側で WHERE 句の絞り込み条件を含めるとどうでしょうか? nestedBuilder := sq.StatementBuilder.PlaceholderFormat(sq.Dollar).Select("x").Prefix("EXISTS ("). From("table1").Where("table2.id = ?", "111").Join("table1 ON table1.column2 = table2.column2").Suffix(")")
d_tutuz

2020/06/11 04:03

ちなみに ON 句で絞り込む、でも同様に絞り込みが実現できると思います。
hello_whats_up

2020/06/11 04:09

その方法で得たい結果を得ることができました! 本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問