ruby-操作mysql
ruby操作mysql数据库
以centos7.2为实验环境
Table of Contents
DBI
安装DBI驱动
-
很多同学在公司是没有外网权限的,可以通过http/https代理使用gem源
- proxy服务器可以使用squid作代理,只需更改端口,其他配置默认即可
- 客户端链接代理设置,假设10.10.239.196为proxy的ip,8889为proxy提供的代理端口
#/etc/profile文件最后添加如下内容
http_proxy=10.10.239.196:8889
https_proxy=10.10.239.196:8889
export http_proxy https_proxy
#使生效
source /etc/profile
安装Mysql开发包
yum install ruby-devel
yum install mysql-devel
- 调整gem源(官方源需要FQ)
#删除默认gem源,安装国内源
gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
#查看当前使用的gem源
gem sources -l
使用RubyGems安装DBI
gem install dbi
gem install mysql
gem install dbd-mysql
连接数据库
- 环境准备
除了安装ruby环境和DBI驱动,假设满足如下条件:
- 一个正常运行的mysql server
- 一个数据库TESTDB
- TESTDB数据库有EMPLOYEE表
- TESTDB数据库用户名testuser,密码"test123"
- 数据库连接示例
#!/usr/bin/env ruby
require 'dbi'
begin
# 连接到 MySQL 服务器
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost",
"testuser", "test123")
# 获取服务器版本字符串,并显示
row = dbh.select_one("SELECT VERSION()")
puts "Server version: " + row[0]
rescue DBI::DatabaseError => e
puts "An error occurred"
puts "Error code: #{e.err}"
puts "Error message: #{e.errstr}"
ensure
# 断开与服务器的连接
dbh.disconnect if dbh
end
执行结果:
Server version: 5.0.45
do方法
do方法直接执行SQL语句,不能传入参数
示例1 删除和创建表:
dbh.do("DROP TABLE IF EXISTS EMPLOYEE")
dbh.do("CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )" );
示例2 插入一条数据
#!/usr/bin/ruby -w
require "dbi"
begin
# 连接到 MySQL 服务器
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost",
"testuser", "test123")
dbh.do( "INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME,
AGE,
SEX,
INCOME)
VALUES ('Mac', 'Mohan', 20, 'M', 2000)" )
puts "Record has been created"
dbh.commit
rescue DBI::DatabaseError => e
puts "An error occurred"
puts "Error code: #{e.err}"
puts "Error message: #{e.errstr}"
dbh.rollback
ensure
# 断开与服务器的连接
dbh.disconnect if dbh
end
prepare加execute方法
prepare方法里面的SQL语句可以带有变量,使用execute方法传入参数。
示例: insert语句
#!/usr/bin/ruby -w
require "dbi"
begin
# 连接到 MySQL 服务器
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost",
"testuser", "test123")
sth = dbh.prepare( "INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME,
AGE,
SEX,
INCOME)
VALUES (?, ?, ?, ?, ?)" )
sth.execute('John', 'Poul', 25, 'M', 2300)
sth.execute('Zara', 'Ali', 17, 'F', 1000)
sth.finish
dbh.commit
puts "Record has been created"
rescue DBI::DatabaseError => e
puts "An error occurred"
puts "Error code: #{e.err}"
puts "Error message: #{e.errstr}"
dbh.rollback
ensure
# 断开与服务器的连接
dbh.disconnect if dbh
end
注:如果同时使用多个 INSERT,那么先准备一个语句,然后在一个循环中多次执行它要比通过循环每次调用 do 有效率得多。
commit和rollback方法
commit是提交操作,rollback是回滚操作。
如果一切进展顺利,则 commit 该操作,否则您可以 rollback 完成交易。
finish方法
释放语句句柄。这将通过使用 finish API 来完成。
DBI异常处理
有许多不同的错误来源。比如在执行 SQL 语句时的语法错误,或者是连接失败,又或者是对一个已经取消的或完成的语句句柄调用 fetch 方法。
如果某个 DBI 方法失败,DBI 会抛出异常。DBI 方法会抛出任何类型的异常,但是最重要的两种异常类是DBI::InterfaceError 和 DBI::DatabaseError。
这些类的 Exception 对象有 err、errstr 和 state 三种属性,分表代表了错误号、一个描述性的错误字符串和一个标准的错误代码。属性具体说明如下:
err:返回所发生的错误的整数表示法,如果 DBD 不支持则返回 nil。例如,Oracle DBD 返回 ORA-XXXX 错误消息的数字部分。
errstr:返回所发生的错误的字符串表示法。
state:返回所发生的错误的 SQLSTATE 代码。SQLSTATE 是五字符长度的字符串。大多数的 DBD 并不支持它,所以会返回 nil。
Mysql2
简述
ruby[Mysql2官档](http://www.rubydoc.info/gems/mysql2/0.2.3/file/README.rdoc)介绍到:
Mysql2是一个现代的,简单的,非常快速的Ruby-Mysql库,用于连接、查询、迭代结果。
Mysql2强制使用UTF-8(或二进制)连接Mysql,如果被设置为其他编码,会从UTF-8转换为指定的编码。
Mysql2驱动的API包含两个类:
- Mysql2::Client 连接数据库的类。
- Mysql2::Result 对当前mysql连接返回一个执行后的结果,包含枚举类型。
安装Mysql2驱动
gem install mysql2
举个🌰
#!/usr/bin/ruby -w
require 'mysql2'
# 连接数据库
client = Mysql2::Client.new(
:host => '127.0.0.1', # 主机
:username => 'root', # 用户名
:password => '123456', # 密码
:database => 'test', # 数据库
:encoding => 'utf8' # 编码
)
# 执行SQL语句
results = client.query("SELECT VERSION()")
# 做循环操作或者使用client.query("SELECT VERSION()").each do |row|
results.each do |row|
puts row
end
Mysql2::Client 配置调整
- 默认的配置方法路径:Mysql2::Client.default_query_options
- 默认配置项为
- 更改配置项方法:
orMysql2::Client.default_query_options.merge!(:as => :array)
orc = Mysql2::Client.new c.query_options.merge!(:symbolize_keys => true)
c = Mysql2::Client.new c.query(sql, :symbolize_keys => true)
异步(Async)
为了充分利用ruby代码的性能,使用异步的方法执行SQL语句
client.query("SELECT sleep(5)", :async => true)
上面的语句会立刻返回nil,而不会停留5s再返回(实际上已经在后台执行了)。期间ruby可以继续执行后面的语句,当socket变为可读后,你可以:
result = client.async_result
注:由于Mysql查询API的工作方式,这个方法会block住,直到执行完毕。如果你使用异步的方法,最好使用一个类似于EventMachine方法监控这个socket。如果你使用多重异步,可以考虑使用connection pool
EventMachine方法
mysql2 EventMachine可以详细的说明异步调用执行是否成功。示例:
require 'mysql2/em'
EM.run do
client1 = Mysql2::EM::Client.new
defer1 = client1.query "SELECT sleep(3) as first_query"
defer1.callback do |result|
puts "Result: #{result.to_a.inspect}"
end
client2 = Mysql2::EM::Client.new
defer2 = client2.query "SELECT sleep(1) second_query"
defer2.callback do |result|
puts "Result: #{result.to_a.inspect}"
end
end
参考文档链接:
http://www.runoob.com/ruby/ruby-database-access.html
http://www.runoob.com/ruby/ruby-mysql-mysql2.html
http://www.rubydoc.info/gems/mysql2/0.2.3/frames