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

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

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

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

SQL

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

Q&A

解決済

5回答

5825閲覧

INSERTしてみて値があればSELECT、なければINSERT

退会済みユーザー

退会済みユーザー

総合スコア0

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

SQL

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

1グッド

2クリップ

投稿2017/03/02 05:19

編集2017/03/02 05:41

SQLiteなのですが、以下のようなテーブルがあるとします。

tb_fruit
id, name_JP, name_EN
0, りんご, apple
1, みかん, orange
2, パイン, pineapple

「name_JPに値をINSERTしてみて、すでに値があればname_ENの値をSELECT、なければname_JPとname_ENに値をINSERT」というクエリーを1行で作りたいのですがわかりません。
name_JP, name_ENはそれぞれQNIQUE制約があります。

例えば
・「みかん」をINSERTしてみるとレコードがあるのでorangeをSELECTしたいです。
・「バナナ」をINSERTしてみるとレコードがないのでバナナとbananaをINSERTしたいです。

そもそもSELECTとINSERTは1行では書けないのでしょうか?

★INSERTを実行した結果、値が存在した場合のみSELECT結果が得られればいいかんじです。
「INSERTが失敗した場合は、レコードが存在するので、そのレコードをSELECT」
「INSERTが成功した場合は、レコードが存在しない(レコードを挿入するのでそもそも値がわかっているためにSELECTしてもしなくてもいい)ので、そのままINSERTのみの実行だけでよい(SELECTしても構わないが)」
みたいな感じだと思うのですが・・・。

どうぞよろしくお願い致します。

pac894398👍を押しています

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

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

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

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

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

guest

回答5

0

ベストアンサー

そもそもSELECTとINSERTは1行では書けないのでしょうか?

INSERTしつつそれに関連する結果セットを得る、という意味であれば、書けないでしょう。

(maisumakunさんの回答に対するコメントより)

一気に連続でこのINSERTとSELECTを数万クエリー発行するので、速度差を調べたい

というのは、

  • 数万件のデータをINSERTしたい
  • ただしすでに存在するデータはINSERTできないので、INSERTできなかったデータを確認したい

という作業をするにあたってレスポンスを気にされている、ということなのでしょうか。

仮にそうだと勝手に仮定して、以下の手順を提案します。

  1. "数万クエリー"分のデータを、別の仮テーブル(例えばtb_fruit_tmp)に全件挿入する
  2. 元テーブル(tb_fruit)にも仮テーブル(tb_fruit_tmp)にも存在するデータをSELECTする
  3. 元テーブル(tb_fruit)には存在しないが仮テーブル(tb_fruit_tmp)には存在するデータを、元テーブルにINSERTする
  4. 用が済んだら仮テーブル(tb_fruit_tmp)をDROPする

1.はINSERTを数万回発行するよりも、.importコマンドを使用したほうが良いかもしれません(未検証)。
とにかく必要な数万件のデータを含む仮テーブルができあがれば、
それと使って元テーブルとの重複をSELECTしたり不足分をINSERTしたり、
は各々単一のSQLで実行できます。

投稿2017/03/02 06:14

編集2017/03/02 06:16
alg

総合スコア2019

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

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

退会済みユーザー

退会済みユーザー

2017/03/02 06:17

ありがとうございます! 数万件のINSERTのことばかり気にしてそちらのほうを考えていませんでした・・・。 たしかに仮テーブル作ってやる方法は検証してみる価値はありそうですね。 ちょっとそちらもやってみようと思います! 別アプローチをいただきまして感謝いたします!
guest

0

回答としては「できない」になります。
そもそも、
INSERTができなければSELECT→値の返却あり
INSERTができればINSERT→値の返却なし
となり、後続の処理が異なってくると思います。
なので、1回の処理で済ますこと自体、何か設計に問題があるのではと思います。
それでも設計は正しいということであれば、結局は2つの処理をしないといけないので、ロジックで分けることになると思います。

通常は…
INSERTできなければUPDATE
INSERTできればINSERT
なんですけどね。
このパターン初めて見ました。

投稿2017/03/02 06:08

ttyp03

総合スコア16998

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

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

退会済みユーザー

退会済みユーザー

2017/03/02 06:10

ありがとうございます。 自分でもこのパターンは初めてだったのでどうなのかな?と思いました。 皆様の見解でやはり無理があるようでした。 2行で進めていきたいと思います!
guest

0

存在しなければINSERT、存在するなら何もしない でよければINSERT OR IGNORE
存在しなければINSERT、存在するなら上書き でよければINSERT OR REPLACE
あたりが使えると思います。

存在しなければINSERT、存在するなら現在の値をSELECTは一行では厳しいと思います。

投稿2017/03/02 05:56

mizuiro_makoto

総合スコア40

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

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

退会済みユーザー

退会済みユーザー

2017/03/02 05:58

ありがとうございます。 やはり1行では難しいのですね・・・。
guest

0

  1. まず先にSELECTする
  2. 結果があればそれを返して終わり
  3. なければINSERTする

この手順ではなにかまずいのでしょうか。

投稿2017/03/02 05:46

maisumakun

総合スコア145183

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

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

退会済みユーザー

退会済みユーザー

2017/03/02 05:49

いえ、まずいわけじゃないんですが一気に連続でこのINSERTとSELECTを数万クエリー発行するので、速度差を調べたいなあと思いまして、もし1行で可能ならやってみたいという感じなのです。
maisumakun

2017/03/02 05:54

根本的に、INSERTは「成功/失敗」、よくて「成功した行数」程度の結果しか返しません。「INSERTの結果として行を受け取る」ということそのものが、(少なくともSqliteでは)不可能です。
退会済みユーザー

退会済みユーザー

2017/03/02 05:59

ありがとうございます。 それがわかっただけでも質問してよかったです! 2行でいこうと思います・・・。
guest

0

・「みかん」をINSERTしてみるとレコードがあるのでorangeをSELECTしたいです。
・「バナナ」をINSERTしてみるとレコードがないのでバナナとbananaをINSERTしたいです。

このロジックがわかりません。
そもそもSELECTとINSERTは1行では書けないのでしょうか?
直接の回答ではありませんが、通常のSQLでは SELECT してWHERE句の条件を満たすデータがなければ INSERT するかと。

投稿2017/03/02 05:29

編集2017/03/02 05:33
Orlofsky

総合スコア16415

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

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

退会済みユーザー

退会済みユーザー

2017/03/02 05:33

ありがとうございます。 それはわかるのですが、2行でしか考えがでません・・・・。
退会済みユーザー

退会済みユーザー

2017/03/02 05:40 編集

「INSERTが失敗した場合は、レコードが存在するので、そのレコードをSELECT」 「INSERTが成功した場合は、レコードが存在しない(レコードを挿入するのでそもそも値がわかっているためにSELECTしてもしなくてもいい)のでINSERTのみ実行でいい(SELECTしてもいいが)」 みたいな感じだと思うのですが・・・。
退会済みユーザー

退会済みユーザー

2017/03/02 06:08

ありがとうございます。 REPLACEしてもSELECT結果が得られないのでちょっと違うようですね・・・。
Orlofsky

2017/03/02 06:16

今のところ、SELECTは別に必要なようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問