トップ «前の日記(2009年05月08日) 最新 次の日記(2009年05月20日)» 編集

Masa's blog

検索キーワード:

2009年05月18日 sqlite3-ruby(1.2.4)儂(わし)的解釈によるメモ [長年日記]

_ sqlite3-ruby(1.2.4)儂(わし)的解釈によるメモ

インストール

sqlite-amalgamation-3.6.14.tar.gz
  • tar xvzf sqlite-amalgamation-3.6.14.tar.gz
  • cd sqlite-3.6.14
  • ./configure
  • make
  • make install
rubygems-1.3.3.tgz
  • tar xvzf rubygems-1.3.3.tgz
  • cd rubygems-1.3.3
  • ruby setup.rb config
  • ruby setup.rb setup
  • ruby setup.rb install
sqlite3-ruby-1.2.4.tar.bz2
  • cd sqlite3-ruby-1.2.4
  • ruby setup.rb config
  • ruby setup.rb setup
  • ruby setup.rb install

サンプルスクリプト

悪魔茶屋 SQLite3のページで紹介されているスクリプトをベースにさせていただいてます。

#! /usr/bin/ruby
require 'rubygems'
require 'sqlite3'
##require 'nkf'
#======================================================================
#
# Databaseへの接続
#
puts "Databaseへの接続"
#
db = SQLite3::Database.new('test.db')
#
# データベース項目へ格納する際に、自動的に型変換する
#
db.type_translation = true
#
# 排他に出会った時の最大待ち時間(msec)
#
#   transaction使用時は無視されるよう?
#
db.busy_timeout(5 * 1000)
#
# 排他に出会った時のトラップハンドラ(busy_timeoutと同時使用不可)
#
#   transaction使用時は無視されるよう?
#
#db.busy_handler("test.db"){|data, retries|
#	print "in busy_handler data is ",data,"\n"
#	print "retries is ",retries,"\n"
#	sleep 1;
#	if (retries <= 3)
#		return true
#	else
#		return false
#	end
#}

#======================================================================
#
# トランザクションの開始(busy_timeout, busy_handlerの使用不可?)
#
#puts "トランザクションの開始"
#
##db.transaction

#======================================================================
#
# テーブル削除(念のため)
#
puts "テーブル削除(念のため)"
#
sql = <<SQL
	drop table member;
SQL

begin
	db.execute(sql)
rescue => e
	if (e.to_s == "no such table: member")
#
# ありがちなエラー(テーブル存在しない)は明示的にトラップ処理
#
		puts "drop error, but continue."
	else
#
# 予測できないエラーはトラップして終了
#
		p e
		puts "drop ERROR = {#{e}}"
		exit 1
	end
end

#======================================================================
#
# テーブル作成
#
puts "テーブル作成"
#
sql = <<SQL
	create table member (
		id INT PRIMARY KEY,
		name TEXT,
		job TEXT
	);
SQL

db.execute(sql)

#======================================================================
#
# 2重にテーブル作成し、わざとエラーを発生させてみる
#
puts "2重にテーブル作成し、わざとエラーを発生させてみる"
#
begin
	db.execute(sql)
rescue => e
	if (e.to_s == "table member already exists")
#
# ありがちなエラー(テーブルは既に存在する)は明示的にトラップ処理
#
		puts "create table error, but continue."
	else
#
# 予測できないエラーはトラップして終了
#
		p e
		puts "create table ERROR = {#{e}}"
		exit 1
	end
end

#======================================================================
#
# インデックス作成
#
puts "インデックス作成"
#
sql = <<SQL
        create index i_member_name on member(name);
SQL

db.execute(sql)

#======================================================================
#
# データセットアップ(バインド機能使用)
#
puts "データセットアップ(バインド機能使用)"
#
sql = "insert into member (id, name, job) values (:id, :name, :job)"
db.execute(sql, :id => 1, :name => '伊藤 太郎', :job => 'サラリーマン')
db.execute(sql, :id => 2, :name => '山田 太郎', :job => '野球選手')
db.execute(sql, :id => 3, :name => '山田 花子', :job => 'タレント')

悪魔茶屋 SQLite3のページではsqlite3にデータを格納する際にはUTF-8にしないといけない旨の記述があるが、実際に生EUCを放り込んでみても特に問題なかった。ただし、他のコード(SJIS etc)だと問題が発生するのかも。

追記:やはりUTF-8でないとマルチバイト文字を検索に利用すると不正な結果を返す事があるようす。

#======================================================================
#
# 2重にデータを作成し、わざとエラーを発生させてみる
#
puts "2重にデータを作成し、わざとエラーを発生させてみる"
#
begin
	db.execute(sql, :id => 3, :name => '山田 花子', :job => 'タレント')
rescue => e
	if (e.to_s == "column id is not unique")
#
# ありがちなエラー(指定したキーは既に存在する)は明示的にトラップ処理
#
		puts "insert error, but continue."
	else
#
# 予測できないエラーはトラップして終了
#
		p e
		puts "insert ERROR = {#{e}}"
		exit 1
	end
end

#======================================================================
#
# データの検索(バインド機能使用)
#
puts "データの検索(バインド機能使用)"
#
sql = "select * from member where id >= :val"
result = db.execute(sql, :val => 1)
#
# 結果レコードが有れば表示する
#
if (result.length > 0)
	p result[0][0].class # => Fixnum
	p result[0][1].class # => String
	p result[0][2].class # => String
end

result.each do |m|
	puts "#{m[0]}\t#{m[1]}\t#{m[2]}"
end

#======================================================================
#
# データの更新(バインド機能使用)
#
puts "データの更新(バインド機能使用)"
#
sql = "update member set job = :job where name = :name"
db.execute(sql, :job => '裁判官', :name => '山田 太郎')

#
# 更新結果の確認
#
puts "更新結果の確認"
#
sql = "select * from member where name = :name"
result = db.execute(sql, :name => '山田 太郎')

result.each do |m|
	puts "#{m[0]}\t#{m[1]}\t#{m[2]}"
end

#======================================================================
#
# データの削除(バインド機能使用)
#
puts "データの削除(バインド機能使用)"
#
sql = "delete from member where name like :name"
db.execute(sql, :name => '山田%')

#
# 削除結果の確認(バインド機能使用)
#
puts "削除結果の確認(バインド機能使用)"
#
sql = "select * from member where id >= :id"
result = db.execute(sql, :id => 1)

result.each do |m|
	puts "#{m[0]}\t#{m[1]}\t#{m[2]}"
end

#======================================================================
#
# トランザクション完了
#
#puts "トランザクション完了"
#
##db.commit

#======================================================================
#
# Databaseからの切断
#
puts "Databaseからの切断"
#
db.close

その他sqlite3の運用に関して

インデックスの再作成は、

$ sqlite3 foo.db reindex

無効領域の開放は、

$ sqlite3 foo.db vacuum