Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - 编程 » SQL Anywhere 数据访问 API » SQL Anywhere for Ruby

 

SQL Anywhere 的 Ruby DBI 驱动程序

本节将概述如何编写使用 SQL Anywhere DBI 驱动程序的 Ruby 应用程序。可从 [external link] http://ruby-dbi.rubyforge.org/ 在线获取 DBI 模块的完整文档。

装载 DBI 模块

要在 Ruby 应用程序中使用 DBI:SQLAnywhere 接口,必须先告诉 Ruby 您打算使用 Ruby DBI 模块。为此,请在 Ruby 源代码文件的顶部附近包括以下行。

require 'dbi'

DBI 模块会根据需要自动装载 SQL Anywhere 数据库驱动程序 (DBD) 接口。

打开和关闭连接

通常,打开一个到数据库的连接,然后通过该连接运行一系列 SQL 语句来执行所有需要的操作。要打开连接,请使用 connect 函数。返回值是一个到数据库连接的句柄,使用该句柄可以在连接上执行后继操作。

对 connect 函数的调用采用一般形式:

dbh = DBI.connect('DBI:SQLAnywhere:server-name', user-id, password, options)
  • server-name   是想要连接到的数据库服务器的名称。也可以按 "option1=value1;option2=value2;..." 的格式指定连接字符串。

  • user-id   是有效用户 ID。除非此字符串为空,否则将 ";UID=value" 附加到连接字符串。

  • password   是用户 ID 的相应口令。除非此字符串为空,否则将 ";PWD=value" 附加到连接字符串。

  • options   是一列附加连接参数,如 DatabaseName、DatabaseFile 和 ConnectionName。这些参数以 "option1=value1;option2=value2;..." 的格式附加到连接字符串。

在使用 connect 函数之前,请启动数据库服务器和示例数据库。

dbeng11 samples-dir\demo.db

以下代码示例打开然后关闭到 SQL Anywhere 示例数据库的连接。下面示例中的字符串 "demo" 是服务器名。

require 'dbi'
DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql') do |dbh|
    if dbh.ping
       print "Successfully Connected\n"
       dbh.disconnect()
    end
end

也可以指定一个连接字符串替换服务器名。例如,在上面的脚本中,可以通过替换 connect 函数的第一个参数进行更改,如下所示:

require 'dbi'
DBI.connect('DBI:SQLAnywhere:ENG=demo;DBN=demo;UID=DBA;PWD=sql') do |dbh|
    if dbh.ping
       print "Successfully Connected\n"
       dbh.disconnect()
    end
end

因为在连接字符串中指定了用户 ID 和口令,所以不必指定 connect 函数的参数 2 和 3。但是,如果传递附加连接参数的散列值,则为用户 ID 和口令参数指定空字符串 ('')。

以下示例说明如何将附加连接参数作为散列键/值对传递到 connect 函数。

require 'dbi'
DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql', 
       { :ConnectionName => "RubyDemo",
         :DatabaseFile => "demo.db",
         :DatabaseName => "demo" }
        ) do |dbh|
    if dbh.ping
       print "Successfully Connected\n"
       dbh.disconnect()
    end
end
选择数据

获得了打开的连接的句柄后,您可以访问和修改存储在数据库中的数据。可能最简单的操作是检索某些行并输出它们。

必须先执行 SQL 语句。如果语句返回结果集,可以使用得到的语句句柄检索有关结果集和结果集行的元信息。以下示例从元数据获得列名,并显示获取的每一行的列名和值。

require 'dbi'

def db_query( dbh, sql )
    sth = dbh.execute(sql)
    print "# of Fields:  #{sth.column_names.size}\n"
    sth.fetch do |row|
        print "\n"
        sth.column_info.each_with_index do |info, i|
            unless info["type_name"] == "LONG VARBINARY"
                print "#{info["name"]}=#{row[i]}\n" 
            end
        end
    end
    sth.finish
end

begin
    dbh = DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql')
    db_query(dbh, "SELECT * FROM Products")
rescue DBI::DatabaseError => e
    puts "An error occurred"
    puts "Error code: #{e.err}"
    puts "Error message: #{e.errstr}"
    puts "Error SQLSTATE: #{e.state}"
ensure
    dbh.disconnect if dbh
end

显示的输出的前几行如下所示。

# of Fields:  8

ID=300
Name=Tee Shirt
Description=Tank Top
Size=Small
Color=White
Quantity=28
UnitPrice=9.00

ID=301
Name=Tee Shirt
Description=V-neck
Size=Medium
Color=Orange
Quantity=54
UnitPrice=14.00

完成后调用 finish 释放语句句柄十分重要。如果不释放句柄,则可能收到如下所示的错误:

Resource governor for 'prepared statements' exceeded

要检测句柄泄漏,缺省情况下 SQL Anywhere 数据库服务器将允许的游标和准备好的语句数量限制为每个连接最多 50 个。如果超过这些限制,资源调控器自动生成错误。如果收到此错误,请检查未被释放的语句句柄。请谨慎使用 prepare_cached,因为语句句柄并没有被释放。

如有必要,可通过设置 max_cursor_count 和 max_statement_count 选项来修改这些限制。请参见max_cursor_count 选项 [数据库]max_statement_count 选项 [数据库]

插入行

插入行需要打开的连接的句柄。插入行最简单的方法是使用参数化的 INSERT 语句,这意味着问号用作值的占位符。首先准备好语句,然后对每一新行执行一次。新行的值作为参数提供给 execute 方法。

require 'dbi'

def db_query( dbh, sql )
    sth = dbh.execute(sql)
    print "# of Fields:  #{sth.column_names.size}\n"
    sth.fetch do |row|
        print "\n"
        sth.column_info.each_with_index do |info, i|
            unless info["type_name"] == "LONG VARBINARY"
                print "#{info["name"]}=#{row[i]}\n" 
            end
        end
    end
    sth.finish
end

def db_insert( dbh, rows )
    sql = "INSERT INTO Customers (ID, GivenName, Surname,
                Street, City, State, Country, PostalCode,
                Phone, CompanyName)
           VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
    sth = dbh.prepare(sql);
    rows.each do |row|
        sth.execute(row[0],row[1],row[2],row[3],row[4],
                    row[5],row[6],row[7],row[8],row[9])
    end
end

begin
    dbh = DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql')
    rows = [
        [801,'Alex','Alt','5 Blue Ave','New York','NY','USA',
            '10012','5185553434','BXM'],
        [802,'Zach','Zed','82 Fair St','New York','NY','USA',
            '10033','5185552234','Zap']
       ]
    db_insert(dbh, rows)
    dbh.commit
    db_query(dbh, "SELECT * FROM Customers WHERE ID > 800")
rescue DBI::DatabaseError => e
    puts "An error occurred"
    puts "Error code: #{e.err}"
    puts "Error message: #{e.errstr}"
    puts "Error SQLSTATE: #{e.state}"
ensure
    dbh.disconnect if dbh
end