2018年4月7日土曜日

Ruby で MySQL の基本操作

概要

mysql2 というライブラリを使って基本操作をしてみました
ruby-mysql という Pure Ruby のライブラリもあるようですが mysql2 のほうがメンテもされているようなのでオススメです

環境

  • macOS 10.13.2
  • Ruby 2.4.1p111
  • mysql2 0.5.0

インストール

MySQL 自体は今回 brew を使ってインストールしてしまいました

  • brew install mysql

ライブラリは RubyGems から引っ張ってきます

  • bundle init
  • vim Gemfile
gem "mysql2"
  • bundle install --path vendor

テスト用のテーブル作成

  • mysql -u root
mysql> create database test;
Query OK, 1 row affected (0.01 sec)

mysql> use test
Database changed
mysql> create table user (id int primary key, name varchar(20), age int, height int, weight int);
Query OK, 0 rows affected (0.03 sec)

でテーブルを作成しました
定義の詳細は以下の通りです

mysql> show create table user \G
*************************** 1. row ***************************
       Table: user
Create Table: CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `height` int(11) DEFAULT NULL,
  `weight` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

データ登録

  • vim insert.rb
require 'mysql2'

client = Mysql2::Client.new(:host => "localhost", :username => "root", :database => 'test')
users = [
  ['pika', 17, 80, 50],
  ['kai', 52, 180, 120],
  ['yado', 34, 120, 150],
  ['pijo', 23, 90, 60],
  ['koda', 2, 70, 65],
  ['kora', 10, 35, 30],
]
users.each.with_index(1) { |user, index|
  query = "insert into user values (#{index}, #{user.map { |v| v.instance_of?(String) ? "'#{v}'" : v }.join(',')})"
  p results = client.query(query)
  p client.affected_rows
}
  • bundle exec ruby insert.rb

で結果は以下の通りです

mysql> select * from user;
+----+------+------+--------+--------+
| id | name | age  | height | weight |
+----+------+------+--------+--------+
|  1 | pika |   17 |     80 |     50 |
|  2 | kai  |   52 |    180 |    120 |
|  3 | yado |   34 |    120 |    150 |
|  4 | pijo |   23 |     90 |     60 |
|  5 | koda |    2 |     70 |     65 |
|  6 | kora |   10 |     35 |     30 |
+----+------+------+--------+--------+
6 rows in set (0.00 sec)

insert 時の結果は何も返ってこないようです
もし insert できた行数が必要な場合はクライアントオブジェクトの affected_rows を参照すると追加したレコードの行数が返ってきます

ちなみに今回は id に PRIMARY_KEY を張っているので同じスクリプトを 2 回流すと Duplicate entry '1' for key 'PRIMARY' (Mysql2::Error) のエラーが発生します

データ取得

  • vim select.rb
require 'mysql2'

client = Mysql2::Client.new(:host => "localhost", :username => "root", :database => 'test')

query = "select * from user"
p results = client.query(query)

statement = client.prepare("select * from user where height >= ?")
conditions = [10, 100, 200] 
conditions.each { |height|
  puts height
  results = statement.execute(height)
  results.each { |row|
    puts row.map { |k, v| "#{k} => #{v}" }.join(', ')
  }
}
  • bundle exec ruby select.rb
10
id => 1, name => pika, age => 17, height => 80, weight => 50
id => 2, name => kai, age => 52, height => 180, weight => 120
id => 3, name => yado, age => 34, height => 120, weight => 150
id => 4, name => pijo, age => 23, height => 90, weight => 60
id => 5, name => koda, age => 2, height => 70, weight => 65
id => 6, name => kora, age => 10, height => 35, weight => 30
100
id => 2, name => kai, age => 52, height => 180, weight => 120
id => 3, name => yado, age => 34, height => 120, weight => 150
200

PreparedStatement も使えます

results は Mysql2::Result クラスのオブジェクトです
中身を確認する場合は基本これを each などします
クエリ自体の状態を確認したい場合は query_was_slow などのプロパティを参照することで確認できます

データ更新

  • vim update.rb
require 'mysql2'

client = Mysql2::Client.new(:host => "localhost", :username => "root", :database => 'test')
target_users = [
  [1, 'raichu'],
  [6, 'ratta'],
]
target_users.each { |user|
  results = client.query("update user set name = '#{user[1]}' where id = #{user[0]}")
  p results
  p client.affected_rows
}

insert の時と挙動は同じです

データ削除

  • vim delete.rb
require 'mysql2'

client = Mysql2::Client.new(:host => "localhost", :username => "root", :database => 'test')
ids = [2, 3]
ids.each { |id|
  results = client.query("delete from user where id = #{id}")
  p results
  p client.affected_rows
}

こんな感じです

最後に

mysql2 を使って Ruby から MySQL の簡単な操作をしてみました
基本は文字列でクエリを作って実行するだけなので簡単にできます

トランザクションの機能はないっぽいので自分で実装する必要があります
https://stackoverflow.com/questions/9288593/how-do-i-perform-transactions-with-ruby-mysql2?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

また active_record のようにモデルを自動生成やマイグレート機能があるわけではないので、その辺も必要な場合は自分で実装する必要があります
とりあえずサクッと MySQL に問い合わせたいときに使う感じかなと思います

0 件のコメント:

コメントを投稿