创建 RDO 参数查询

如果需要执行的 SQL 查询的 WHERE 子句中包含一个或一个以上的参数,那么可以使用 rdoQuery 对象来运行该查询,并且在每一次执行时管理这些参数。对于需要重复运行,或对于几个连接运行的查询,这种方法非常有用,尤其是执行参数化的存储过程的时候。

提示   可以创建自己的查询,与参数一起构成一个完整的 SQL 语句。有时这种方法可能是创建参数查询的唯一方法,特别是查询很复杂,或以特殊方式使用远程数据库语法的时候。

任何情况下,提交的 SQL 语句都必须在语法上正确。与参数查询相关的许多问题都源于远程服务器所要求的原始 SQL 编码或者下述的 ODBC SQL 语法不正确。提交语法不正确的查询会导致各种各样的问题,包括远程引擎返回的语法错,以及 RDO 无法创建 rdoParameters 集合等。

用 rdoParameters 集合管理参数

如果希望 RDO 使用 rdoParameters 集合来管理参数,可以在 SQL 语句的每一个参数的位置包含一个问号。"?" 用作输入、输出以及输入/输出查询参数的占位符。代码通过设置 Direction 属性表明了占位符与参数之间的对应关系。RDO 和 ODBC 接口自动管理这些参数,并按照预先定义的数据类型将每个参数绑定到一个 rdoParameter 对象。有时候代码可能要强制指定某些参数的数据类型。尤其是在查询中包含表达式,表达式的自变量作为参数传递的时候。

所有参数都被标记和标识之后,RDO 和 ODBC 接口将自动创建与 驱动器有关的 SQL 语句,以及一个 rdoParameters 集合以管理参数值和数据类型。在大多数情况下,不必为用作参数的字符串加引号,也不必关心其它的格式问题。

注意   在创建 rdoQuery 对象时,并没有进行语法检查。只有执行该查询或者访问 rdoParameters 集合时,才会编译它并为其参数赋值。如果语句中有语法错误,可能会触发可以捕获的 40054 “非法参数”错误,或其它一些 ODBC 错误。有些情况下,rdoParameters 集合没有成功地创建,因此在被引用时可能会产生可以捕获的错误,表明该对象不存在。

提示   虽然可能在有效 ODBC 驱动程序列表中发现 DAO (Access) 数据库的 ODBC 驱动程序,但它们不符合 ODBC Level II。可以使用 RDO 向该驱动器提交查询,并返回结果集,但它不能象遵循 Level II 的驱动程序那样创建 rdoParameter 对象或者管理查询参数。

为参数查询选择正确的 SQL 语法

在编写 rdoQuery 对象的 SQL 属性或 OpenResultset 方法的 name 参数时,可以选择以下三种风格之一来编写参数查询:

注意   SQL Server ODBC 驱动程序要求所有非捆绑的参数(在代码中被连接到查询的参数)都显示在占位符参数(那些以“?”标记的参数)的右边。如果不这样做,将产生一个可以捕获的错误:"Wrong number of parameters"。

ODBC CALL 语法的优点及局限

使用 ODBC CALL 语法有许多的优点。例如,ODBC 使用开放数据系统远程过程来执行查询。参数以它们原始的形式传递,不需要进行分析或类型转换。这也意味着 ODBC 不需要为处理查询而“预先准备”,因为它已经以存储过程的形式存在于远程服务器上了。这样调用的效率更高,并且数据库之间的可移植性更强。

使用 rdExecDirect 执行参数查询

在执行过程时,rdExecDirect 选项强制 RDO 使用 ODBC API SQLExecDirect 函数。这样就省略了 ODBC API SQLPrepare 这一步骤,后者用于创建一个执行查询的临时过程。当需要的 SQL 语句可以被远程服务器接受,但不能被 ODBC 接口接受时,可以使用该选项。但是,在执行存储过程参数查询时不能使用它,因为这会妨碍参数进行正确的类型绑定。

注意   在有些情况下,在关闭连接之前不能删除 ODBC 接口创建的临时存储过程。使用 rdExecDirect 选项可以避免这个问题。

语法选项总结

下表总结了使用三种语法风格时可用的选项:

语法选项

功能 Native SQL 语法 ODBC Call

语法

Concatenated strings
能否传递未引用存储过程的原始 SQL?
可以执行存储过程?
参数能否使用 ? 占位符?
管理返回值
管理输出参数
SQL 语句是否可以包括多个 Select 语句?

注意   RDO 管理 RDO 参数集合中的查询参数的能力是有条件的,需要 ODBC 接口能够正确地分析查询,并且能够确定参数的正确类型。在有些情况下,ODBC 驱动程序管理器无法正确标识一个 SQL 语句中的所有参数。这时,可以将该语句转换成一个存储过程,即便是临时的,可能就可以使查询成为可用的。

提示   虽然 ODBC Call 语法可以用于不需传递参数或没有返回值的情况下,通常,只有在需要获得存储过程的返回状态和输出参数时才使用它。

编写一个典型的参数查询

参数查询仅仅是将用户或应用程序提供的参数代入普通的查询中。该查询通常是 SELECT 语句,但也可以是 INSERT, UPDATE 或 DELETE 查询。下面的例子说明如何编写带有一个参数的简单 SELECT 查询。该查询从 Pubs 范例数据库中查询特定姓名的作者。

首先,设置一个 SQL 查询,并用 ? 标记其中每一个参数。

QSQL$ = "SELECT * FROM Authors WHERE Au_Lname = ?"

然后,创建一个 rdoQuery 对象以管理该查询及其参数。

Set PSAuthors = cn.CreateQuery("",QSQL$)

下一步,使用以下代码将用户输入的值 (Text1.Text) 插入到该查询。

PSAuthors.rdoParameters(0) = Text1.Text

注意,这里的 rdoParameters 对象可以是隐含的,因为它是 rdoQuery 对象的缺省集合。与其等价的代码是:

PSAuthors(0) = Text1.Text

然后,创建一个 rdoResultset 对象,取得满足条件的数据列(名字与参数值一致的数据列)。

Set MyRs = CpwPSAuthors.OpenResultset()

如果用户改变了参数值 Text1.Text,可以对 rdoResultset(MyRs) 使用 Requery 方法,重新应用新的参数并重新执行查询,并不需要重建 rdoQuery 对象。

PSAuthors(0) = Text1.Text
MyRs.Requery

当 RDO 执行 Requery 方法时,它会更新与查询参数相联的 rdoParameters 集合中的参数值,清除当前的结果集,将查询送到数据源执行,并创建一个新的 rdoResultset。

请记住该查询是在什么时候首次创建的,RDO 和 ODBC 层在远程服务器上创建了一个临时的存储过程,用来接收参数。每次执行该查询时,只需将新的参数传递到这个临时的查询并执行它。

提示   如果使用了带 rdAsyncEnable 选项的 OpenResultset 方法,在使用 Requery 方法时也要设置该选项。

注意   在执行不带参数的存储过程时,不要在 SQL 语句中包含括号。例如,为了执行不带参数的 "MySP" 过程,可以使用如下语句:

{Call MySP }

如果用户更改了参数值,那么可以使用 rdoResultset (MyRs) 的 Requery 方法,用新的参数值重新执行该查询。

Cpw(0) = Text1.Text
MyRs.Requery

参数的连接

将参数连接到 SQL 语句字符串,也可以为 SQL 查询指定参数。例如,要提交采用这种方法的一个查询,可以使用以下代码:

QSQL = "SELECT * FROM Authors WHERE Au_Lname = '" _
 & Text.Text & "'"
Set MyRs = Cn.OpenResultSet(QSQL)

这种情况下,不会创建 rdoParameters 集合,也不能引用它。要修改查询参数,那么在查询执行的时候或使用 Requery 方法之前,必须用新的参数值重建该 SQL 语句。另外,除非使用了 rdExecDirect 选项,否则,每次使用 OpenResultset 方法时,RDO 都将创建一个新的临时存储过程,并执行该查询。

详细信息   请参阅《语言参考》中的 “rdoQuery 对象”、“rdoParameter 对象”、“Requery 方法”和“OpenResultset 方法”部分。关于存储过程的其它信息,请参阅“使用 RDO 执行存储过程”。