ruby-操作mysql

ruby操作mysql数据库

以centos7.2为实验环境


Table of Contents

  1. 使用DBI访问Mysql
  2. 使用Mysql2访问Mysql

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驱动,假设满足如下条件:

  1. 一个正常运行的mysql server
  2. 一个数据库TESTDB
  3. TESTDB数据库有EMPLOYEE表
  4. 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
  • 默认配置项为
  • 更改配置项方法:
    Mysql2::Client.default_query_options.merge!(:as => :array)
    
    or
    c = Mysql2::Client.new
    c.query_options.merge!(:symbolize_keys => true)
    
    or
    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

posted @ 2018-03-16 18:29  MauriceWei  阅读(585)  评论(0编辑  收藏  举报