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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

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

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

3回答

2731閲覧

SQL文でRailsでいうところのfind_or_initialize_byを生成したいです。(PythonのMySQLdbでSQLを作成してます。)

qaz3330

総合スコア113

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

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

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2016/06/19 09:01

編集2016/06/19 10:02

pythonでMySQLdbを用いて、SQL文を作成しております。

今回やりたいこととしましては、
Railsでいうところのfind_or_initialize_byのような処理をSQL文で生成したいです。

DBに対象レコードがあれば取得し、なければ、initializeするといったことです。

200件ほどデータがあり(今後も増える)、ループを回し、そのループの中で、SQL文を生成しなくてはいけないため、
純粋にSELECT文をしてなければ、INSERTをするといったことをすると処理に時間がかかってしまうため、
initializeのようなことができればなと思いました。

よろしくお願いします。

補足

皆様の回答を拝見して補足します。

find_or_initialize_byでは、DBに保存されないので、
ここだけのSQLを見るのはおかしいという点、理解出来ました。

また、今回の一番の趣旨は、find_or_create_byのようにやると、
INSERT文がループの回数だけ発生してしまうため、
そうではなく、一括で更新できるようなSQL文を作成したいです。

そういう点では、Bulk insertなどが近いのかなと思いました。
とはいえど、すべてが既存レコードというわけではないので、
レコードが見つからなかったら、newして、・・・と考えていたら、find_or_initialize_by

に辿り着きました。

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

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

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

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

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

guest

回答3

0

使えるとしたら、INSERT ... ON DUPLICATE KEY UPDATE構文でしょうか。

https://dev.mysql.com/doc/refman/5.6/ja/insert-on-duplicate.html

SQL

1INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) 2 ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

MySQLだと上記の文法が使え、「INSERTしようとして主キーがすでにINSERT済みの場合はUPDATEをする」という、いわゆるUPSERT的な命令が可能です。
また、複数INSERTしようとする例もあるみたいなので、何か使いどころがあるかもしれません。

投稿2016/06/19 10:10

attakei

総合スコア2738

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

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

0

参考情報

Active Record クエリインターフェイス
このガイドでは、Active Recordを使用してデータベースからデータを取り出すためのさまざまな方法について解説します。
...
Client.find_or_create_by(first_name: 'Andy')
...
SELECT * FROM clients WHERE (clients.first_name = 'Andy') LIMIT 1
BEGIN
INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 1, NULL, '2011-08-30 05:22:57')
COMMIT
...
find_or_initialize_byメソッドはfind_or_create_byと同様に動作しますが、createの代りにnewを呼ぶ点が異なります。つまり、モデルの新しいインスタンスは作成されますが、その時点ではデータベースに保存されていません。
...

追加 2016-06-19 23:20

merge についての参考情報:

...
DB2 のプログラミング
MERGE ステートメントを使用すれば、単一の操作によって既存のデータを更新し、新規データを挿入できます。
...

...
FOR UPDATE
...
条件に一致するレコードが表にあれば更新、なければ挿入(新規追加)する場合、普通にSELECTしてレコードが無かったらUPDATEするという方法では、SELECT時にレコードが存在してもUPDATE時にそのレコードがまだ存在している保証はない。そこで、SELECT FOR UPDATEを使うと、レコードロックがかかり、UPDATEするまで削除されない。なお、SELECT FOR UPDATEを実行した場合、コミットするまでロックされたままなので注意が必要である。Oracle 9i以降ではMERGE文を使用するのが望ましい。
...

...
「りんご」は価格更新(UPDATE)、「めろん」は新商品(INSERT)として扱いたいと思います。 テーブルを結合させた無名カーソルを用いて、旧価格が取れた(NOT NULL)なら更新、そうでなければ追加…というロジックでPL/SQLで素直にコーディングしてみました。
...
これをMERGEで書き換えると…
...

投稿2016/06/19 09:44

編集2016/06/19 14:21
katoy

総合スコア22324

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

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

qaz3330

2016/06/19 10:04

railsguideのページありがとうございます。 ちなみに今回やりたいことをふまえ、質問本文に追記しました。
guest

0

Railsでfind_or_initialize_byを実行した時のサーバログに実際に実行されたSQLの文が表示されるのでそれを確認すれば良いのでは?

投稿2016/06/19 09:06

realizerS

総合スコア265

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

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

qaz3330

2016/06/19 09:09

SELECT `categories`.* FROM `categories` WHERE `categories`.`name` = 'hoge' LIMIT 1
qaz3330

2016/06/19 09:15 編集

こういうSQLになってしまい、質問本文で書いたような問題が発生するかと思います。まだ経験が浅いので判断がつかないのですが、これでいいものなんでしょうか? 200件ループさせると、短期間の間に200回、インサートすることになるかと思いました。
realizerS

2016/06/19 09:20

find_or_initialize_byはselectして結果を確認し、存在すればその結果を、存在しなければnewを実行した結果を返すメソッドですからDBにinsertはされません。 なければinsertってことなら find_or_create_by の結果を確認したほうがよいかも知れません。
qaz3330

2016/06/19 10:03

ご回答ありがとうございます。少なくとも、find_or_initialize_byではないですね。勉強になりました。また、今回やりたいことをふまえ、質問本文に追記しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問