Ruby - 数据库访问

首页 / Ruby / Database Access

本章教您如何使用Ruby访问数据库。 Ruby DBI 模块为Ruby脚本提供了与Perl DBI模块类似的独立于数据库的接口。

DBI代表Ruby的数据库独立接口,这意味着DBI在Ruby代码和基础数据库之间提供了一个抽象层,使您可以真正轻松地切换数据库实现。

如果要编写Ruby脚本来访问MySQL数据库,则需要安装Ruby MySQL模块。

如上所述,此模块充当DBD,可以从 https://www.tmtm.org/en/mysql/ruby/

安装Ruby/DBI

您可以从以下位置下载并安装Ruby DBI模块-

https://imgur.com/NFEuWe4/embed

在开始此安装之前,请确保您具有root特权。现在,按照下面给出的步骤-

第1步

$tar zxf dbi-0.2.0.tar.gz

第2步

进入分发目录 dbi-0.2.0 并使用该目录中的 setup.rb 脚本对其进行配置。最通用的配置命令如下所示,在config参数后面没有参数。此命令将分发配置为默认情况下安装所有驱动程序。

$ruby setup.rb config

更具体地说,提供--with选项,列出要使用的发行版的特定部分。例如,要仅配置主DBI模块和MySQL DBD级驱动程序,请发出以下命令-

$ruby setup.rb config --with=dbi,dbd_mysql

第3步

最后一步是构建驱动程序并使用以下命令进行安装-

$ruby setup.rb setup
$ruby setup.rb install

数据库连接

以下是连接MySQL数据库" TESTDB"的示例

#!/usr/bin/ruby -w

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

运行此脚本时,它将在Linux机器上产生以下输出。

Server version: 5.0.45

如果与数据源创建了连接,则将返回数据库句柄并将其保存到 dbh 中以供进一步使用,否则将 dbh 设置为nil值和 e.err e::errstr 分别返回错误代码和错误字符串。

插入数据

要在数据库表中创建记录时需要INSERT操作。

创建数据库连接后,准备使用 do 方法或 prepareexecute 方法在数据库表中创建表或记录。

使用do语句

可以通过调用 do 数据库句柄方法来发出不返回行的语句。此方法采用语句字符串参数,并返回该语句影响的行数的计数。

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 )" );

同样,您可以执行SQL INSERT 语句在EMPLOYEE表中创建一条记录。

#!/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

您可以使用DBI类的准备和 execute 方法通过Ruby代码执行SQL语句。

记录创建采取以下步骤-

以下是使用这两种方法的语法-

sth=dbh.prepare(statement)
sth.execute
   ... zero or more SQL operations ...
sth.finish

这两种方法可用于将 bind 值传递给SQL语句。在某些情况下,可能不会事先给出要输入的值。在这种情况下,将使用绑定值。使用问号(?)代替实际值,然后将实际值通过execute()API传递。

以下是在EMPLOYEE表中创建两个记录的示例-

#!/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 方法或 prepareexecute 方法从数据库表中获取值。

记录获取采取以下步骤-

  • 根据所需条件准备SQL查询。这将使用 prepare 方法完成。

  • 执行SQL查询以从数据库中选择所有输出。这将使用 execute 方法来完成。

  • 一个接一个地获取所有输出并打印这些输出。这将使用 fetch 方法完成。

  • 释放语句句柄。这将使用 finish 方法完成。

以下是从薪水超过1000的EMPLOYEE表中查询所有记录的过程。

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh=DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth=dbh.prepare("SELECT * FROM EMPLOYEE WHERE INCOME > ?")
   sth.execute(1000)

   sth.fetch do |row|
   printf "First Name: %s, Last Name : %s\n", row[0], row[1]
   printf "Age: %d, Sex : %s\n", row[2], row[3]
   printf "Salary :%d\n\n", row[4]
end
   sth.finish
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

这将产生以下输出-

First Name: Mac, Last Name : Mohan
Age: 20, Sex : M
Salary :2000

First Name: John, Last Name : Poul
Age: 25, Sex : M
Salary :2300

更新数据

UPDATE对任何数据库进行的操作意味着更新一个或多个记录,这些记录已在数据库中可用。以下是更新所有SEX为'M'的记录的过程。在这里,无涯教程将所有男性的年龄提高一年。这将采取三个步骤-

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh=DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth=dbh.prepare("UPDATE EMPLOYEE SET AGE=AGE + 1 WHERE SEX=?")
   sth.execute('M')
   sth.finish
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

删除数据

要从数据库中删除某些记录时,需要执行DELETE操作。以下是从AGE大于20的EMPLOYEE删除所有记录的过程。此操作将执行以下步骤。

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh=DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth=dbh.prepare("DELETE FROM EMPLOYEE WHERE AGE > ?")
   sth.execute(20)
   sth.finish
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

执行事务

事务是一种确保数据一致性的机制。事务应具有以下四个属性-

  • 原子性 - 要么事务完成,要么什么都没有发生。

  • 一致性 - 事务必须以一致的状态开始并且离开系统的是一致的状态。

  • 隔离性 - 事务的中间输出在当前事务之外不可见。

  • 耐久性 - 提交事务后,即使在系统出现故障后,影响也将持久存在。

DBI提供两种方法来 commitrollback 事务。还有一种叫做 transaction 的方法,可以用来实现事务。有两种简单的方法来实现事务-

第一种方法使用DBI的 commitrollback 方法来显式提交或取消事务-

dbh['AutoCommit']=false # Set auto commit to false.
begin
   dbh.do("UPDATE EMPLOYEE SET AGE=AGE+1 WHERE FIRST_NAME='John'")
   dbh.do("UPDATE EMPLOYEE SET AGE=AGE+1 WHERE FIRST_NAME='Zara'")
   dbh.commit
rescue
   puts "transaction failed"
   dbh.rollback
end
dbh['AutoCommit']=true

第二种方法使用 transaction 方法。这比较简单,因为它需要一个包含构成事务的语句的代码块。 transaction 方法执行该块,然后自动调用 commitrollback ,具体取决于该块是成功还是失败-

dbh['AutoCommit']=false # Set auto commit to false.
dbh.transaction do |dbh|
   dbh.do("UPDATE EMPLOYEE SET AGE=AGE+1 WHERE FIRST_NAME='John'")
   dbh.do("UPDATE EMPLOYEE SET AGE=AGE+1 WHERE FIRST_NAME='Zara'")
end
dbh['AutoCommit']=true

提交数据

Commit是一项操作,它向数据库发出绿色信号以完成更改,并且在执行此操作后,将无法还原任何更改。

这是调用 commit 方法的简单示例。

dbh.commit

回滚数据

如果您对一项或多项更改不满意,并且想要完全还原这些更改,请使用 rollback 方法。

这是调用 rollback 方法的简单示例。

dbh.rollback

断开数据库

要断开数据库连接,请使用断开连接API。

dbh.disconnect

如果用户使用断开连接方法关闭了与数据库的连接,则DBI将回滚所有未完成的事务。

处理错误

错误的来源很多。一些示例是已执行的SQL语句中的语法错误,连接失败或为已取消或完成的语句句柄调用fetch方法。

如果DBI方法失败,则DBI引发异常。 DBI方法可以引发几种类型的异常中的任何一种,但是两个最重要的异常类是 DBI::InterfaceError 和 DBI::DatabaseError 

这些类的异常对象具有名为 err , errstr 和 state 的三个属性,分别表示错误编号,描述性错误字符串和标准错误代码。属性说明如下-

  • err       -  返回发生的错误的整数表示形式;如果DBD不支持,则返回 nil 。例如,Oracle DBD返回数字部分 ORA-XXXX 错误消息的内容。

  • errstr   - 返回所发生错误的字符串表示形式。

  • state    - 返回发生错误的SQLSTATE代码。SQLSTATE是一个五个字符的字符串。大多数DBD不支持此功能,而是返回nil。

您已经在大多数示例中看到了以下代码-

无涯教程网

rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

要获取有关脚本执行时的操作的调试信息,可以启用跟踪。为此,您必须首先加载dbi/trace模块,然后调用控制跟踪模式和输出目标的 trace 方法-

require "dbi/trace"
..............

trace(mode, destination)

模式值可以是0(关闭),1、2或3,并且目标应该是IO对象。默认值分别为2和STDERR。

带方法的代码块

有一些创建句柄的方法。可以使用代码块来调用这些方法。将代码块与方法一起使用的优点是,它们将代码块的句柄作为其参数提供,并在代码块终止时自动清除该句柄。很少有例子可以理解这个概念。

  • DBI.connect - 此方法生成数据库句柄,建议在该块末尾调用 disconnect 断开数据库连接。

  • dbh.prepare  - 此方法生成一个语句句柄,建议在该块的末尾完成。在该块中,您必须调用 execute 方法来执行该语句。

  • dbh.execute  - 此方法类似,除了不需要在块内调用execute。语句句柄将自动执行。

DBI.connect 可以获取一个代码块,将数据库句柄传递给它,并按如下所述自动断开该块末尾的句柄。

dbh=DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") do |dbh|

dbh.prepare 可以获取一个代码块,将语句句柄传递给它,然后按如下所示在该块的末尾自动调用finish

dbh.prepare("SHOW DATABASES") do |sth|
   sth.execute
   puts "Databases: " + sth.fetch_all.join(", ")
end

dhb.execute 可以获取一个代码块,将语句句柄传递给它,并在代码块末尾自动调用finish,如下所示:

dbh.execute("SHOW DATABASES") do |sth|
   puts "Databases: " + sth.fetch_all.join(", ")
end

DBI transaction 方法还采用了上面已描述的代码块。

函数列表和属性

DBI使数据库驱动程序提供附加的特定于数据库的功能,用户可以通过任何Handle对象的 func 方法调用这些功能。

支持特定于驱动程序的属性,可以使用 []=或 [] 方法进行设置或获取。

#!/usr/bin/ruby

require "dbi"
begin
   # connect to the MySQL server
   dbh=DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") 
   puts dbh.func(:client_info)
   puts dbh.func(:client_version)
   puts dbh.func(:host_info)
   puts dbh.func(:proto_info)
   puts dbh.func(:server_info)
   puts dbh.func(:thread_id)
   puts dbh.func(:stat)
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
ensure
   dbh.disconnect if dbh
end

这将产生以下输出-

5.0.45
50045
Localhost via UNIX socket
10
5.0.45
150621
Uptime: 384981  Threads: 1  Questions: 1101078  Slow queries: 4\
Opens: 324  Flush tables: 1  Open tables: 64\
Queries per second avg: 2.860

这一章《Ruby - 数据库访问》你学到了什么?在下面做个笔记吧!做站不易,你的分享是对我们最大的支持,感谢!😊

相关文章

Java核心技术面试精讲 -〔杨晓峰 - 44讲〕

JavaScript核心原理解析 -〔周爱民 - 28讲〕

性能测试实战30讲 -〔高楼 - 37讲〕

OAuth 2.0实战课 -〔王新栋 - 17讲〕

Ruby符号前面的“-”是什么意思?

我可以使用 `else if` 而不是 `elsif` 吗?

数组.include?多个值

使用 bundler 只更新一个 gem

对于基于 GitHub 的 gem,强制Bundle 安装使用 https:// 而不是...

如何期望 RSpec should_receive 的一些(但不是全部)参数?

视频推荐〔什么Ruby〕

更多视频 »
好记忆不如烂笔头。留下你的足迹吧 :)