yshの日記 このページをアンテナに追加 RSSフィード

2008-06-29

[][]Ruby Sequel DBアクセスライブラリ

Objecttank@rubyDBアクセスライブラリDBIからSequelに移行中。

Sequelの参考ページ

  1. http://sequel.rubyforge.org/
  2. http://www.slideshare.net/zhesto/ruby-off-rails-japanese
  3. http://xxx.mostevildanceclassics.com/page/r/SequelRuby

インストール

sudo gem install sequel

とりあえず実行

sequelのコマンドラインツール。railsscript/consoleのようなもの。

sequel mysql://user:password@localhost/dbname

DBという名前の変数に接続オブジェクトが格納される

テーブル名=userがあったとすると、、、

DB[:user].filter(:id => 10).all # 検索
DB[:user]<<{:id => 11, :name =>'yshgt'} # 登録

これだけ。定義とかいらない。

基本情報

対応DB

SQLite3, PostgreSQL, Oracle, MySQL, ODBC, Informix, DBI, ADO(Windows)

チートシート

データベース接続
require 'rubygems'
require 'sequel'

options = {}
# 各DB毎の接続メソッドを利用する場合
DB = Sequel.sqlite # オンメモリDB
DB = Sequel.sqlite('dbname.db' , options)
DB = Sequel.ado('dbname', options)
DB = Sequel.mysql('dbname', options)
DB = Sequel.postgres('dbname', options)

# DB共通の接続メソッドconnectを利用する場合
DB = Sequel.connect('sqlite:/') # オンメモリDB
DB = Sequel.connect('sqlite://dbname.db') # ./dbname.db
DB = Sequel.connect('sqlite:///dbname.db') # /dbname.db
DB = Sequel.connect('sqlite:///dbname.db', options)
DB = Sequel.connect('postgres://user:password@host/dbname', options)
DB = Sequel.connect('mysql://user:password@host/dbname', options)

optionsはMySQLの接続設定情報

optionsはハッシュで第二引数に指定してもいいし、第二引数以降に可変長引数でそれぞれ指定してもいい。

dbopts = Hash.new
dbopts[:host] = 'localhost'
dbopts[:user] = 'scott'
dbopts[:password] = 'tiger'
dbopts[:database] = 'scott'
dbopts[:encoding] = 'utf8'
dbopts[:max_connections] = 5
dbopts[:loggers] = Logger.new('test.log', 'daily')

第一引数の接続情報と第二引数のoptionsはどちらかに指定していればいい。

極端にやると

options = {:user=>"username", :password=>"password", database=>"databasename"}
DB = Sequel.mysql(nil, options)
DB = Sequel.connect("mysql:/", options)

でもよい。

SQL実行
dataset = DB["show variables"]
dataset.each do |row|
  p row.values.to_a
end
p dataset.size # 取得行数
Select
dataset = DB[:user].filter(:name => 'username')
dataset = DB[:user].filter((:age <= 20) & (:age >= 15))  # and
dataset = DB[:user].filter((:age >= 20) | (:age <= 15))  # or 
dataset = DB[:user].filter(:age => 15..20) # age >=15 and age <= 20
dataset = DB[:user].filter(:age => 15...20) # age >=15 and age < 20
dataset = DB[:user].filter(:name.like('ysh%'))

dataset = DB[:user].filter(:age > 10).order(:age)
dataset = DB[:user].filter(:age > 10).order(:age.desc, :sex.asc)
dataset = DB[:user].filter(:age > 10).reverse_order(:age)
# ↑この時点ではSQL文を作っただけ。↓で実行される。あってる?

p dataset.count # 行数
# p dataset.max(:age) #うまくいかない?  
# p dataset.min(:age)
# p dataset.avg(:age)
# p dataset.sum(:age)

p dataset.columns #=> [:id, :name, :age, :sex]

dataset.each do |r|
  p r[:id]
end

ページング・リミット

dataset.limit(10, 0) #=> limit 10 offset 0
paginate = dataset.paginate(1, 10) # 1ページ10行の1ページ目 = limit 10 offset 0 上と同じ
paginated.page_count #=> ページ数
paginated.current_page #=> 今のページ番号
paginated.next_page #=> 次のページ番号(なければnil)
paginated.prev_page #=> 前のページ番号(なければnil)
paginated.first_page? #=> 1ページ目だったらtrue
paginated.last_page? #=> 最後のページだったらtrue

結合

dataset = DB[:user].left_outer_join(:company, :id => :company_id)
Update文
DB[:user].filter(:name => 'username').update(:password => 'newpassword')
Insert文
DB[:user].insert(:name => 'yamada taro', :age=> 21)
DB[:user] << {:name => 'sato ichiro', :grade => 32}

こまったこと

mysqlの場合は、DB接続時にencoding指定をすればよかった。

DB=Sequel.connect("mysql://user:password@localhost/dbname", {:encoding=>"utf8"})
  • 直接SQL指定で実行する場合に名前付きバインド変数を使いたいな〜

たぶん今は?だけ

トラックバック - http://d.hatena.ne.jp/yshgt/20080629/1214720897