Ruby 与 Oracle 数据库交互
为了使 Ruby 能够与我们的 Oracle 数据库通信,需要使用 Ruby/OCI8。可从 http://rubyforge.org/projects/ruby-oci8/ 获得。尽管我们可以用交互式 IRB 编写自己的 Ruby 代码来访问数据库,但这种方法比较费事。较好的方法是:将我们的数据库访问代码编写成一个 Ruby 脚本文件,然后用 ruby 解释器命令运行该 Ruby 脚本文件。
Ruby 与 Oracle DDL SQL。 我们首先创建一个用于创建新表的 Ruby 脚本文件。我们需要声明与 Ruby/DBI 结合使用的是一个 require 语句,然后使用 Ruby/DBI API。清单 1 显示以上内容和 CREATE 语句。
清单1:createStatesTable.rb
|
清单 1 中的大多数代码都是您在 SQL*Plus 或 SQL Developer 中用于创建一个新数据库表的 SQL 代码。数据库连接字符串包括 DBI:OCI8:ORCL 字符串以及用户名和口令(本示例中为 hr/hr)。DBI 部分是标准内容,OCI8 部分指的是 Ruby/OCI8 驱动程序,ORCL 部分指的是数据库服务。可以使用简单的 createStatesTable.rb 命令在命令行执行这个 createStatesTable.rb 文件。如果一切顺利,则不会提供任何反馈,但该表将处于 HR 模式中。
继续介绍 Ruby 的其他数据库操作之前,需要指出 ruby 解释器命令允许您检查脚本的语法而无需实际运行它。例如,如果要测试 createStatesTable.rb 脚本中的语法而不实际创建该表,我可以使用 -c 选项,如下: ruby -c createStatesTable.rb.
清单 1 中与 Ruby 有关的另一件有趣的事情是未定义变量 dbh 的数据类型。与其他动态脚本编写语言一样,Ruby 不需要声明变量的数据类型,而是根据变量的上下文来假定所需的数据类型。在其余的 Ruby 代码清单中,我们将看到更多这样的“动态类型 (duck typing)”— 如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子。
Ruby 与 Oracle DML SQL。 创建了一个 STATES 表之后,我们来填充它。我们将向该表中插入几个代表性的州名,如清单 2 所示。
清单2:populateStatesTable.rb
|
清单 2 中有一些需要了解的 Ruby/DBI 新特性。首先,注意问号在 INSERT 语句中用作占位符。这很有用,因为它允许创建该语句一次,然后针对插入到表中的每个代表性州名进行填充。由于 INSERT 语句是一个 DML 语句(与清单 1 中的 DDL CREATE 语句不同),因此在该清单中还需要一个 COMMIT 调用。
执行了这两个 Ruby 脚本之后,您就具有了一个名为 STATES 的数据库表,其中填充了几个州。现在,假设您在一些州的首府上犯了一些典型错误,甚至弄混了一个州的缩写(用 MA 代表 Maine,实际上 MA 代表 Massachusetts)。
清单 3 显示了用以修复这些问题的简单 UPDATE 脚本。清单 3 用占位符更新州首府并直接更新 Maine 的错误缩写,而不使用任何占位符或任何类型的语句准备。
清单3:updateStatesTable.rb
|
正如您希望的那样,DELETE 的执行方式与其同等的 DML 语句 INSERT 和 UPDATE 的执行方式非常类似。因此,您现在将转到一条 SELECT 语句,因为该语句添加了一个新技巧:数据库查询的结果集。
清单 4 演示如何在我们新填充的 STATES 表上执行一个简单查询。内置的 p 函数打印出返回的行,如图 5 所示。您可能已经使用内置的 puts 方法或 pp(“优化打印程序”)库来显示查询结果。清单 4 显示使用 # 指示有关打印查询结果的这两种方式的 Ruby 内联注释。
清单4:queryStatesTable.rb
|
图5:查询结果 |
Ruby DBI 提供了更好的输出格式。清单 5 和 6 显示使用 DBI 分别以表格和 XML 格式输出相同的查询结果。清单 5 和 6 中的代码不仅显示了 DBI::Utils 输出格式功能的用法,还显示了与清单 4 略微不同的获取和操作结果集的方法。
清单5:queryStatesTableFormatter.rb
|
图 6 和 7 分别显示了这些脚本产生的表格式输出和 XML 输出。
图6:查询结果的表格式输出 |
图7:XML 格式的查询结果 |
您现在已经利用 Ruby 和 Oracle 执行了基本的 CRUD(CREATE、RETRIEVE、UPDATE 和 DELETE)操作。现在该介绍结合使用 Ruby 和 Oracle 存储过程的示例了。
Ruby 与 Oracle 存储过程。 PL/SQL 是许多基于 Oracle 数据库的应用程序频繁使用的语言。由于用户已经对 Oracle 存储过程投入了大量的资源、时间以及从实际经验中吸取的教训,因此您使用的任何语言可以访问大量已证明的功能是很重要的。
清单 7 显示用于访问 PL/SQL 内置存储过程 DBMS_UTILITY.DB_VERSION(接受两个 OUT 参数)的代码,您的代码显示通过这两个 OUT 参数传回的结果。
清单7:builtInDBVersionCompat.rb
|
图 8 显示了运行该 Ruby 代码的显示结果。
图8:Ruby 访问内置 DBMS_UTILITY.DB_VERSION 的结果 |
清单 7 还有另一个需要注意的有趣地方。该清单演示了 Ruby 符号(本例中为 :bind_value)的使用,还显示了使用 DBI::Handle(本例中名为 sth_db)函数方法调用特定于该 Ruby DBI 数据库驱动程序的功能。
清单 8 中的代码演示了使用 Ruby DBI 运行内置的存储函数 DBMS_METADATA.GET_DDL。由于多方面的原因,这个内置函数很有用,下面有关如何获取 Ruby DBI 中某个函数的返回值的示例就是其中一个原因。该函数需要将对象类型和对象名与几个可选参数一起传入。在这种情况下,您只传入两个必需的参数,并使用名称批注传递它们。
清单8:builtInGetDDL.rb
|
DBMS_METADATA.GET_DDL 函数可返回创建我们指定的表所需的 DDL。注意,这是有用的信息,因为它为我们提供了我们重新创建表时将需要的 DDL。返回的 DDL 明显比我们的 CREATE TABLE 语句更具体,因为它显式说明了我们假定的设置。查看这些结果可以更深入地了解 Oracle 数据库的工作,帮助数据库专业人员决定要更改和调整的参数。
除了显示如何访问 Oracle 存储函数的返回值之外,清单 8 还显示了与我们先前使用的不同的绑定变量的方法。在之前具有绑定变量的清单(清单 7)中,我们使用的是位置绑定,这意味着您将问号 (?) 放在数据库执行字符串中,并使用从 1 开始的连续整数来引用值。在清单 8 中,您使用的是名称绑定,这意味着我们放入的是 Ruby 符号(如本例中的 :out1、:in1 和 :in2),稍后通过名称引用这些绑定变量以访问其值。Ruby 对位置绑定与名称绑定的支持与 PL/SQL 对位置参数批注和命名参数批注的支持类似。图 9 显示了运行清单 8(用于创建我们的 STATES 表的 DDL)的结果。
图9:DBMS_METADATA.GET_DDL 中的 DDL create 语句 |