5.4 在 XDS 事件中嵌入 SQL 语句

下一节包括的信息可帮助您在 XDS 事件中嵌入 SQL。

所有示例均参照以下 indirect.usr 表。

CREATE TABLE indirect.usr ( idu   INTEGER  NOT NULL, fname VARCHAR2(64), lname VARCHAR2(64),

    CONSTRAINT pk_usr_idu PRIMARY KEY(idu) );

使用嵌入式 SQL,可以在 XDS 格式的 XML 文档中嵌入 SQL 语句。 可以结合 XDS 事件使用嵌入式 SQL 语句,也可以单独使用这些语句。 如果单独使用嵌入式 SQL 语句,则嵌入式 SQL 处理不需要驱动程序知道有关目标数据库中的表/视图的任何信息。 因此,驱动程序可以在纲要不兼容的方式下运行。请参见同步过滤器。 如果单独使用嵌入式 SQL,则必须手动建立关联。 驱动程序不建立关联。

与 XDS 事件结合使用时,嵌入式 SQL 可充当虚拟的数据库触发器。 同样,可以在表中安装数据库触发器,在执行了特性的 SQL 语句后,便可以在数据库中产生副作用。嵌入式 SQL 可以在数据库中产生副作用以响应特定的 XDS 事件。

5.4.1 嵌入式 SQL 的常见用途

在 XDS 事件中嵌入 SQL 可实现以下目的:

  • 创建数据库用户或职能。
  • 管理用户口令

    可以设置、检查或修改用户口令。

  • 管理数据库用户或职能特权。

样本配置文件 JDBCv2.xml 说明如何创建数据库用户、管理用户口令,以及将用户特权作为 XDS 事件的副作用进行管理。 要启用数据库用户帐户管理,请将全局配置变量 (GCV) user-ddl 设置为真。 《订购者》通道上的用户 DDL 命令转换样式页中包含了嵌入式 SQL 的示例。

5.4.2 嵌入式 SQL 基本知识

要素

SQL 通过 <jdbc:statement><jdbc:sql> 要素嵌入到 XDS 事件中。 <jdbc:statement> 要素可以包含一个或多个 <jdbc:sql> 要素。

名称空间

如果在 XML 文档以外参照本节各个部分使用的名称空间前缀 jdbc,该前缀将被隐式联结到名称空间 urn:dirxml:jdbc

必须使用带有名称空间前缀的嵌入式 SQL 要素和特性。否则,驱动程序将无法识别它们。 在本节的所有示例中,使用的前缀均为 jdbc。 事实上,只要前缀与名称空间值 urn:dirxml:jdbc 联结,就可以使用任意前缀。

以下 XML 示例说明如何使用嵌入式 SQL 要素,以及如何正确地为其添加名称空间前缀。 以下示例中的名称空间声明和名称空间前缀显示为粗体:

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <jdbc:sql>UPDATE indirect.usr SET fname = 'John'</jdbc:sql> </jdbc:statement> </input>

嵌入式 SQL 示例

以下 XML 示例说明如何使用 <jdbc:statement><jdbc:sql> 要素及其解释。 以下示例中的嵌入式 SQL 要素显示为粗体:

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <jdbc:sql>UPDATE indirect.usr SET fname = 'John'</jdbc:sql> </jdbc:statement> </input>

由于《订购者》通道将 <add> 事件解析为一个或多个 INSERT 语句,因此上面显示的 XML 将解析为:

SET AUTOCOMMIT OFF INSERT INTO indirect.usr(lname)VALUES('Doe'); COMMIT; --explicit commit UPDATE indirect.usr SET fname = 'John'; COMMIT; --explicit commit

5.4.3 令牌替代

《订购者》通道支持嵌入式 SQL 语句中的令牌替代,而不是要求您分析关联中的字段值。 在以下示例中,令牌及其参照的值显示为粗体:

<input xmlns:jdbc="urn:dirxml:jdbc"> <modify class-name="usr"> <association>idu=1,table=usr,schema=indirect</association> <modify-attr name="lname"> <add-value> <value>DoeRaeMe</value> </add-value> </modify-attr> </modify> <jdbc:statement> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>

令牌占位符必须遵守 XSLT 特性值模板语法 {$field-name}。 同时,参照的关联要素必须在 XDS 文档中的 <jdbc:statement> 要素之前,或者以 <jdbc:statement> 要素子项的形式存在。 或者,将包含关联要素的要素的 src-entry-id 复制到 <jdbc:statement> 要素,而不是将关联要素作为 <jdbc:statement> 要素的子项进行复制。 在以下示例中,这两种方法均显示为粗体:

<input xmlns:jdbc="urn:dirxml:jdbc"> <modify class-name="usr"> <association>idu=1,table=usr,schema=indirect</association> <modify-attr name="lname"> <add-value> <value>DoeRaeMe</value> </add-value> </modify-attr> </modify> <jdbc:statement>            <association>idu=1,table=usr,schema=indirect</association> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>
<input xmlns:jdbc="urn:dirxml:jdbc"> <modify class-name="usr" src-entry-id="0"> <association>idu=1,table=usr,schema=indirect</association> <modify-attr name="lname"> <add-value> <value>DoeRaeMe</value> </add-value> </modify-attr> </modify> <jdbc:statement src-entry-id="0"> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>

{$field-name} 令牌必须参照关联值中的命名 RDN 特性名之一。 以上示例只有一个命名特性: idu

只有在 <add> 事件中,才不需要关联要素位于包含令牌的嵌入式 SQL 语句之前,因为尚未创建关联。 此外,使用令牌的任何嵌入式 SQL 语句必须接在 <add> 事件之后,而不是在它的前面。例如:

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>

为防止跟踪敏感信息,可以使用 {$$password} 令牌来参照同一文档中紧靠在前面的 <password> 要素的内容。 在以下示例中,口令令牌及其参照的值显示为粗体:

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <password>some password</password> <add-attr name="fname"> <value>John</value> </add-attr> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <jdbc:sql>CREATE USER jdoe IDENTIFIED BY {$$password}</jdbc:sql> </jdbc:statement> </input>

此外,还可以参照 Application Password 参数指定为 {$$$driver-password} 的、驱动程序的数据库鉴定口令。请参见应用程序口令。 暂时不支持命名的口令替代。

正如同关联要素一样,参照的口令要素必须在 XDS 文档中的 <jdbc:statement> 要素之前,或者以 <jdbc:statement> 要素子项的形式存在。 或者,将包含口令要素的要素的 src-entry-id 复制到 <jdbc:statement> 要素,而不是将口令要素作为 <jdbc:statement> 要素的子项进行复制。 在以下示例中,这两种方法均显示为粗体:

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <password>some password</password> <add-attr name="fname"> <value>John</value> </add-attr> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <password>some password</password> <jdbc:sql>CREATE USER jdoe IDENTIFIED BY {$$password}</jdbc:sql> </jdbc:statement> </input>
<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr" src-entry-id="0"> <password>some password</password> <add-attr name="fname"> <value>John</value> </add-attr> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement src-entry-id="0"> <jdbc:sql>CREATE USER jdoe IDENTIFIED BY {$$password}</jdbc:sql> </jdbc:statement> </input>

5.4.4 虚拟触发器

与数据库触发器可以在触发语句之前或之后进行触发的方式一样,可以将嵌入式 SQL 定位在触发 XDS 事件之前或之后。 以下示例显示如何将 SQL 嵌入在 XDS 事件之前或之后。

事件前面的虚拟触发器

<input xmlns:jdbc"urn:dirxml:jdbc"> <jdbc:statement>           <association>idu=1,table=usr,schema=indirect</association>           <jdbc:sql>UPDATE indirect.usr SET fname = 'John' WHERE                     idu = {$idu}</jdbc:SQL>     </jdbc:statement>     <modify class-name="usr">         <association>idu=1,table=usr,schema=indirect</association>         <modify-attr name="lname">             <remove-all-values/>             <add-value>                 <value>Doe</value>             </add-value>         </modify-attr>     </modify> </input>

该 XML 将解析为:

SET AUTOCOMMIT OFF UPDATE indirect.usr SET fname = 'John' WHERE idu = 1; COMMIT; --explicit commit UPDATE indirect.usr SET lname = 'Doe'  WHERE idu = 1; COMMIT; --explicit commit

事件后面的虚拟触发器

<input xmlns:jdbc"urn:dirxml:jdbc">     <modify class-name="usr">         <association>idu=1,table=usr,schema=indirect</association>         <modify-attr name="lname">             <remove-all-values/>             <add-value>                 <value>Doe</value>             </add-value>     </modify-attr>     </modify>     <jdbc:statement>         <jdbc:sql>UPDATE indirect.usr SET fname = 'John' WHERE                                       idu = {$idu}</jdbc:sql>     </jdbc:statement> </input>

该 XML 将解析为:

SET AUTOCOMMIT OFF UPDATE indirect.usr SET lname = 'Doe'  WHERE idu = 1; COMMIT; --explicit commit UPDATE indirect.usr SET fname = 'John' WHERE idu = 1; COMMIT; --explicit commit

5.4.5 手动事务与自动事务

可以使用两个自定义特性对嵌入式 SQL 和 XDS 事件进行手动分组:

  • jdbc:transaction-type
  • jdbc:transaction-id

jdbc:transaction-type

该特性具有两个值: manualauto。 默认情况下,会将大多数相关的 XDS 事件(<add><modify><delete>)隐式设置为手动事务类型。 通过手动设置,XDS 事件可以解析为由一个或多个 SQL 语句组成的事务。

默认情况下,会将嵌入式 SQL 事件设置为自动事务类型,因为某些 SQL 语句(例如 DDL 语句)通常不能包含在手动事务中。 在以下示例中,该特性显示为粗体文本。

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr" jdbc:transaction-type="auto"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>

该 XML 将解析为:

SET AUTOCOMMIT ON INSERT INTO indirect.usr(lname) VALUES(’Doe’); -- implicit commit UPDATE indirect.usr SET fname = ’John’ WHERE idu = 1; -- implicit commit

jdbc:transaction-id

除非要素的 jdbc:transaction-type 特性值默认为或显式设置为 manual,否则《订购者》通道将忽略该特性。 以下 XML 显示了手动事务的示例。 特性显示为粗体文本。

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr" jdbc:transaction-id="0"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement jdbc:transaction-type="manual"                     jdbc:transaction-id="0"> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>

该 XML 将解析为:

SET AUTOCOMMIT OFF INSERT INTO indirect.usr(lname) VALUES('Doe’); UPDATE indirect.usr SET fname = ’John’ WHERE idu = 1; COMMIT; -- explicit commit

5.4.6 事务隔离级别

除了对语句进行分组外,还可以使用事务来保持数据库中数据的完整性。 事务可以锁定数据,以防对其进行并行访问或修改。 事务的隔离级别确定锁的设置方式。 通常,驱动程序使用的默认隔离级别的功能已足够,因此不应更改。

如果必要,可以使用自定义特性 jdbc:isolation-level 来调整事务隔离级别。 java.sql.Connection 参数可在接口中定义五个可能值。 请参见 java.sql.Connection

  • none
  • read uncommitted
  • read committed
  • repeatable read
  • serializable

除非描述符文件覆盖了驱动程序的默认事务隔离级别,否则该级别为 read committed。 在手动事务中,请将 jdbc:isolation-level 特性放置在事务中的第一个要素上。 将忽略后续要素上的该特性。 在以下示例中,该特性显示为粗体文本。

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr" jdbc:transaction-id="0"                      jdbc:isolation-level="serializable"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement jdbc:transaction-type="manual" jdbc:transaction-id="0"> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>

该 XML 将解析为:

SET AUTOCOMMIT OFF SET TRANSACTION ISOLATION LEVEL SERIALIZABLE INSERT INTO indirect.usr(lname) VALUES(’Doe’); UPDATE indirect.usr SET fname = ’John’ WHERE idu = 1; COMMIT; -- explicit commit

5.4.7 语句类型

《订购者》通道可以执行嵌入式 SQL 语句,但它不理解这些语句。 JDBC 1 接口可以定义用于执行不同类型的 SQL 语句的多种方法。 下表包含这些方法:

Table 5-21 SQL 语句的执行方法

语句类型

执行方法

SELECT

java.sql.Statement.executeQuery(String query):java.sql.ResultSet

INSERT

java.sql.Statement.executeUpdate(String update):int

UPDATE

java.sql.Statement.executeUpdate(String update):int

DELETE

java.sql.Statement.executeUpdate(String update):int

CALL 或 EXECUTE SELECT INSERT UPDATE DELETE

java.sql.Statement.execute(String sql):boolean

最简单的解决方案是将所有 SQL 语句映射到 java.sql.Statement.execute(String sql):boolean 方法。 默认情况下,《订购者》通道使用该方法。

某些第三方驱动程序(尤其是 Oracle 的 JDBC 驱动程序)会不正确地实现某些方法来确定该方法生成的结果集数目。 因此,驱动程序可能会陷入无限循环之中,从而导致较高的 CPU 利用率。 要避免此问题,可以使用任何 <jdbc:statement> 要素上的 jdbc:type 特性,将该要素包含的 SQL 语句映射到下列方法而不是默认方法:

  • java.sql.Statement.executeQuery(String query):java.sql.ResultSet
  • java.sql.Statement.executeUpdate(String update):int

jdbc:type 特性有两个值: updatequery。 对于 INSERTUPDATEDELETE 语句,请将值设置为 update。 对于 SELECT 语句,请将值设置为 query。 如果缺少该特性,驱动程序会将所有 SQL 语句映射到默认方法。 如果将该特性放置在除 <jdbc:statement> 以外的其它任何要素上,该特性将被忽略。

建议:

  • jdbc:type=”query” 特性值放置在所有 SELECT 语句上。
  • jdbc:type=”update” 特性值放置在所有 INSERT、UPDATEDELETE 语句上。
  • 不要将特性值放置在储存过程/函数调用上。

以下 XML 显示 jdbc:type 特性的示例。 该特性显示为粗体文本。

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement jdbc:type="update"> <jdbc:sql>UPDATE indirect.usr SET fname = ’John’ WHERE idu = {$idu}</jdbc:sql> </jdbc:statement> </input>

5.4.8 SQL 查询

为完全支持数据库的查询功能,以及避免将本机 SQL 查询转换为 XDS 格式时存在的困难,驱动程序可以支持本机 SQL 查询处理。 可以按嵌入其它任何 SQL 语句完全相同的方法,将 select 语句嵌入 XDS 文档。

例如,假定 usr 表具有以下内容:

Table 5-22 示例内容

idu

fname

lname

1

John

Doe

以下 XML 文档将导致生成包含单个结果集的输出文档。

<input xmlns:jdbc="urn:dirxml:jdbc"> <jdbc:statement jdbc:type="query"> <jdbc:sql>SELECT * FROM indirect.usr</jdbc:sql> </jdbc:statement> </input>
<output xmlns:jdbc="urn:dirxml:jdbc"> <jdbc:result-set jdbc:number-of-rows="1"> <jdbc:row jdbc:number="1"> <jdbc:column jdbc:name="idu"  jdbc:position="1"  jdbc:type="java.sql.Types.BIGINT <jdbc:value>l</jdbc:value> </jdbc:column>             <jdbc:column jdbc:name="fname" jdbc:position="2" jdbc:type="java.sql.Types.VARCHAR> <jdbc:value>John</jdbc:value> </jdbc:column> <jdbc:column jdbc:name="lname" jdbc:position="3"                          jdbc:type="java.sql.Types.VARCHAR> <jdbc:value>Doe</jdbc:value> </jdbc:column> </jdbc:row> </jdbc:result-set> <status level="success"/> </output>

无论结果集是否包含任何行,SQL 查询始终都会生成单个 <jdbc:result-set> 要素。 如果结果集为空,jdbc:number-of-rows 特性将设置为零。

可以在一个文档中嵌入多个查询。 SQL 查询不要求同步纲要中的参照表/视图对驱动程序可见。 但是,XDS 查询有此要求。

5.4.9 数据定义语言 (DDL) 语句

一般而言,无法运行数据库触发器中的数据定义语言 (DDL) 语句,因为大多数数据库不允许将 DML 和 DDL 事务相混合。 尽管虚拟触发器没有克服这种事务限制,但是,它们确实允许将 DDL 语句作为 XDS 事件的副作用来执行。

例如:

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <add-attr name="fname"> <value>John</value> </add-attr> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <jdbc:sql>CREATE USER jdoe IDENTIFIED BY novell</jdbc:sql> </jdbc:statement> </input>		

该 XML 将解析为:

SET AUTOCOMMIT OFF INSERT INTO indirect.usr(fname, lname) VALUES(’John’, ’Doe’); COMMIT; -- explicit commit SET AUTOCOMMIT ON CREATE USER jdoe IDENTIFIED BY novell; -- implicit commit

如果使用 jdbc:transaction-idjdbc:transaction-type 特性将 DML 和 DDL 语句分组成单个事务,那么在大多数数据库中,该事务将会回滚。 由于 DDL 语句一般是作为不同的事务执行的,因此以上示例中的 insert 语句可能会成功,并且 create user 语句可能会回滚。

但是,insert 语句不可能失败,而 create user 语句不可能成功。 驱动程序将在第一个事务回滚的位置停止执行链接的事务。

5.4.10 逻辑运算

由于一般情况下不能将 DML 和 DDL 语句混合在单个事务中,因此单个事件可能包括一个或多个事务。 可以使用 jdbc:op-idjdbc:op-type 将多个事务一起分组到单个逻辑运算中。 以这种方式分组后,会根据状态将运算的所有成员作为一个单元进行处理。 如果有一个成员出错,所有成员都将返回相同的状态级别。 同样,所有成员都将共享相同的状态类型。

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr" jdbc:op-id="0" jdbc:op-type="password-set-operation"> <add-attr name="fname"> <value>John</value> </add-attr> <add-attr name="lname"> <value>Doe</value> </add-attr> <password>Doe{$idu}</password> </add> <jdbc:statement jdbc:op-id="0"> <jdbc:sql>CREATE USER jdoe IDENTIFIED BY {$$password} </jdbc:sql> </jdbc:statement> </input>

除逻辑运算中的第一个要素外,其它所有要素上的 jdbc:op-type 特性都将被忽略。

5.4.11 使用嵌入式 SQL 实现口令集

通常,最初的口令设置是通过创建数据库用户帐户来完成的。 假定在《订购者》通道上生成了 <add> 事件,下面是 XSLT 样式页生成的输出示例,该样式页将口令集作为 XDS <add> 事件的副作用来实现:

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr" jdbc:op-id="0" jdbc:op-type="password-set-operation"> <add-attr name="fname"> <value>John</value> </add-attr> <add-attr name="lname"> <value>Doe</value> </add-attr> <password>Doe{$idu}</password> </add> <jdbc:statement jdbc:op-id="0"> <jdbc:sql>CREATE USER jdoe IDENTIFIED BY {$$password} </jdbc:sql> </jdbc:statement> </input>

jdbc:op-idjdbc:op-type 特性将 <add> 事件按逻辑联结到 CREATE USER DDL 语句。

JDBCv2.xml 样本配置文件中的 User DDL 命令转换样式页包含样本 XSLT 模板,这些模板可将用户帐户创建 DDL 语句联结到支持这些语句的所有数据库的 <add> 事件。

5.4.12 使用嵌入式 SQL 实现修改口令

通常,最初的口令设置是通过更改现有的数据库用户帐户来完成的。 假定在《订购者》通道上生成了 <modify-password> 事件,下面是实现 modify-password 的 XSLT 样式页生成的输出示例:

<input xmlns:jdbc="urn:dirxml:jdbc"> <modify-password jdbc:op-id="0" jdbc:op-type="password-set-operation"> <password>new password</password> </modify-password> <jdbc:statement jdbc:op-id="0"> <jdbc:sql>ALTER USER jdoe IDENTIFIED BY {$$password} </jdbc:sql> </jdbc:statement> </input>

jdbc:op-idjdbc:op-type 特性将 <modify-password> 事件按逻辑联结到 ALTER USER DDL 语句。

JDBCv2.xml 样本配置中的 User DDL 命令转换样式页包含样本 XSLT 模板,这些模板可将口令维护 DDL 语句联结到支持这些语句的所有数据库的 <modify-password> 事件。

5.4.13 实现检查对象口令

与口令集不同,检查对象口令不需要嵌入式 SQL 语句或特性。 只需要一个用户帐户名。 可以从关联值(假定正在手动维护关联)、目录特性或数据库字段中获取该用户帐户名。 如果该值储存在目录或数据库中,则必须发出查询来检索该值。

JDBCv2.xml 样本配置文件在数据库字段中储存数据库用户帐户名。

NOTE:某些数据库(例如 Sybase Adpative Server Enterprise 和 Microsoft SQL Server)区分用户帐户名和登录帐户名。 因此,可能需要储存两个名称,而不只是一个。

要实现检查对象口令,请将 dest-dn 特性值追加到 <check-object-password> 事件。 在以下示例中,dest-dn 特性显示为粗体:

<input xmlns:jdbc="urn:dirxml:jdbc"> <check-object-password dest-dn="jdoe"> <password>whatever</password> </check-object-password> </input>

5.4.14 最佳做法

出于性能方面的考虑,最好是调用一个包含多个 SQL 语句的储存过程/函数,而不是将多个语句嵌入 XDS 文档。

在以下示例中,最好使用单个储存过程或函数。

单个储存过程

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <add-attr name="fname"> <value>John</value> </add-attr> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement> <jdbc:sql>CALL PROCEDURE set_name('John', 'Doe')</jdbc:sql> </jdbc:statement> </input>

多个嵌入的语句

<input xmlns:jdbc="urn:dirxml:jdbc"> <add class-name="usr"> <add-attr name="lname"> <value>Doe</value> </add-attr> </add> <jdbc:statement>         <jdbc:sql>UPDATE indirect.usr SET fname = 'John'                   WHERE idu = {$idu}</jdbc:sql>     </jdbc:statement>     <jdbc:statement>         <jdbc:sql>UPDATE indirect.usr SET lname = 'Doe'                   WHERE idu = {$idu}</jdbc:sql>     </jdbc:statement> </input>

用于调用储存过程或函数的语法随数据库的不同而异。有关其它信息,请参见储存过程和函数 JDBC 调用语法