LoginSignup
0
1

More than 3 years have passed since last update.

Ruby mysql2 で prepareする際の注意点

Last updated at Posted at 2019-07-01

Ruby mysql2の動作でよくわからないところ

Ruby mysql2でqueryとprepareで動作が違う。これが仕様なのかどうなのかわからない。

バージョン

ruby : ruby 2.1.1.p76
mysql2 : 0.5.2

準備

検証用テーブルを作成。

create.sql
CREATE TABLE t_test (
  no int(11) DEFAULT NULL,
  test_date date DEFAULT NULL,
  article varchar(256) DEFAULT NULL
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8
;

検証用データを挿入。

insert into t_test values
('1',now(),'date on'),
('2',null,'date null'),
('3','0000-00-00','date space')
;

データ確認

mysql> select * from t_test ;
+------+------------+------------+
| no   | test_date  | article    |
+------+------------+------------+
|    1 | 2019-07-01 | date on    |
|    2 | NULL       | date null  |
|    3 | 0000-00-00 | date space |
+------+------------+------------+
3 rows in set (0.00 sec)

mysql> select * from t_test where test_date is null;
+------+-----------+-----------+
| no   | test_date | article   |
+------+-----------+-----------+
|    2 | NULL      | date null |
+------+-----------+-----------+
1 row in set (0.00 sec)

mysql> select * from t_test where test_date <> '0000-00-00';
+------+------------+------------+
| no   | test_date  | article    |
+------+------------+------------+
|    1 | 2019-07-01 | date on    |
+------+------------+------------+
1 row in set (0.00 sec)

ま、当たり前の結果。

Rubyからデータを取得してみる。

queryで抽出してみる。

mysql2_query.rb
#! /usr/local/bin/ruby
require 'mysql2'
require 'pp'

cli = Mysql2::Client.new(:host => '127.0.0.1', :username => '***', :password => '***', :database => '***' ,:encoding => 'utf8')

sql1 = %{select no,test_date,article from t_test limit 10}
ret1 = cli.query(sql1 ,:symbolize_keys => true)
ret1.each do |row|
    p row
end

queryでデータを呼び出すと普通に出力される。

[anno@sv1]~/bin% ./mysql2_query.rb
{:no=>1, :test_date=>#<Date: 2019-07-01 ((2458666j,0s,0n),+0s,2299161j)>, :article=>"date on"}
{:no=>2, :test_date=>nil, :article=>"date null"}
{:no=>3, :test_date=>nil, :article=>"date space"}
[anno@sv1]~/bin% 

prepare + executeで抽出してみる。

mysql2_prepare_1.rb
#! /usr/local/bin/ruby
require 'mysql2'
require 'pp'

cli = Mysql2::Client.new(:host => '127.0.0.1', :username => '***', :password => '***', :database => '***' ,:encoding => 'utf8')

sql2 = %{select no,test_date,article from t_test limit ?}
stmt = cli.prepare(sql2)
ret2 = stmt.execute('10' ,:symbolize_keys => true)
ret2.each do |row|
    p row
end
[anno@sv1]~/bin% ./mysql2_prepare_1.rb
/usr/local/lib/ruby/gems/2.1.0/gems/mysql2-0.5.2/lib/mysql2/statement.rb:7:in `new': invalid date (ArgumentError)
        from /usr/local/lib/ruby/gems/2.1.0/gems/mysql2-0.5.2/lib/mysql2/statement.rb:7:in `each'
        from /usr/local/lib/ruby/gems/2.1.0/gems/mysql2-0.5.2/lib/mysql2/statement.rb:7:in `_execute'
        from /usr/local/lib/ruby/gems/2.1.0/gems/mysql2-0.5.2/lib/mysql2/statement.rb:7:in `block in execute'
        from /usr/local/lib/ruby/gems/2.1.0/gems/mysql2-0.5.2/lib/mysql2/statement.rb:6:in `handle_interrupt'
        from /usr/local/lib/ruby/gems/2.1.0/gems/mysql2-0.5.2/lib/mysql2/statement.rb:6:in `execute'
        from ./mysql2_prepare_1.rb:18:in `<main>'
[anno@sv1]~/bin% 

prepareでデータを呼び出すとエラーが出る。invalid date???

prepare + executeで抽出してみる(その2)。

dateでエラーとのことなので、日付がnullのデータを排除してselectしてみると成功。

mysql2_prepare_2.rb
#! /usr/local/bin/ruby
require 'mysql2'
require 'pp'

cli = Mysql2::Client.new(:host => '127.0.0.1', :username => '***', :password => '***', :database => '***' ,:encoding => 'utf8')

sql2 = %{select no,test_date,article from t_test where test_date <> '0000-00-00' limit ?}
stmt = cli.prepare(sql2)
ret2 = stmt.execute('10' ,:symbolize_keys => true)
ret2.each do |row|
    p row
end
[anno@sv1]~/bin% ./mysql2_prepare_2.rb
{:no=>1, :test_date=>#<Date: 2019-07-01 ((2458666j,0s,0n),+0s,2299161j)>, :article=>"date on"}
[anno@sv1]~/bin% 

結論

理由はわからないけど、prepareでデータ抽出をするときは日付データがnullは許容されないらしい。

  • SQL側で文字列に変化させてからデータ抽出をする
  • prepareをあきらめてqueryで抽出する
  • テーブル構造で日付にnull,0000-00-00を許容しない様子にする。 どれかで対処する。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1