技术开发 频道

使用DB2的LOAD FROM CURSOR转移数据

  在另一个数据库中创建表拷贝的简便方法

  既然已经了解了使用别名的远程 LOAD FROM CURSOR 操作方法,现在看看另一种比较简便的方法。为此,首先删除刚才在目标数据库 MYSAMPLE 中的 SALES 表中导入的所有行,见清单 16。

  清单 16. 删除目标表中的所有行,以便再次执行 LOAD FROM CURSOR 操作

C:\>db2 "CONNECT TO MYSAMPLE"

  
Database Connection Information

  
Database server = DB2/NT 9.5.2

  SQL
authorization ID = FECHNER

  Local
database alias = MYSAMPLE

  C:\
>db2 "DELETE FROM FECHNER.SALES"

  DB20000I The SQL command completed successfully.


  对于第二种方法,不需要配置对远程数据库的联邦访问。只需使用 DATABASE 选项在 DECLARE CURSOR 语句中指定远程数据库。为此,要在本地 DB2 实例的系统数据库目录中对远程数据库进行编目。前面已经给出了所需的 CATALOG 命令。另外,在定义游标时要指定远程访问所需的用户名和密码。LOAD 命令本身保持不变。

  清单 17. 在不使用别名的情况下执行远程 LOAD FROM CURSOR 操作 

C:\>db2 "DECLARE C1 CURSOR DATABASE SRCDB USER fechner USING password FOR SELECT * FROM

  FECHNER.SALES"

  DB20000I The SQL command completed successfully.

  C:\
>db2 "LOAD FROM C1 OF CURSOR MESSAGES C:\load_sales_2.msg INSERT INTO FECHNER.SALES

  NONRECOVERABLE"

  
Number of rows read = 41

  
Number of rows skipped = 0

  
Number of rows loaded = 41

  
Number of rows rejected = 0

  
Number of rows deleted = 0

  
Number of rows committed = 41

  C:\
>db2 "TERMINATE"

  DB20000I The TERMINATE command completed successfully.


  从 DB2 9.1 开始,可以以这种方式执行远程 LOAD FROM CURSOR 操作,这种方式基于 DB2 8 中的联邦访问方法。这种新方法有两个优点 —— 容易使用且性能好。显然,新方法非常容易使用。性能比联邦方法好是因为涉及的数据传输层更少。但是,不应该忘记联邦方法的优点,即可以访问非 DB2 数据源。

  CLP 和 ADMIN_CMD 在 LOAD FROM CURSOR 方面的差异

  可以通过特殊的存储过程 ADMIN_CMD 执行许多管理命令,从而把管理命令嵌入在应用程序代码中。这也适用于 LOAD FROM CURSOR 操作。存储过程 ADMIN_CMD 的使用与应用程序代码的位置无关,也就是说,在客户端代码(例如 Java 应用程序)和服务器端代码(例如 SQL/PL 存储过程)中都可以使用它。下面的示例在一个定制的 SQL/PL 存储过程中使用 ADMIN_CMD 存储过程。create_load_routine.sql 文件包含示例存储过程 REMOTE_LOAD_FROM_CURSOR 的 SQL/PL 源代码。

  清单 18. 包含示例存储过程的 create_load_routine.sql 文件

CREATE PROCEDURE FECHNER.REMOTE_LOAD_FROM_CURSOR ()

  SPECIFIC REMOTE_LOAD_FROM_CURSOR

  LANGUAGE SQL

  
BEGIN

  
DELETE FROM FECHNER.SALES;--

  CALL SYSPROC.ADMIN_CMD (
'LOAD FROM (DATABASE SRCDB SELECT * FROM FECHNER.SALES) OF

  CURSOR INSERT INTO FECHNER.SALES NONRECOVERABLE
');--

  
END;


  存储过程中的第一个语句是 DELETE,它删除本地目标表 SALES 中现有的行。接下来,用适当的 LOAD 命令调用 ADMIN_CMD,从而执行远程 LOAD FROM CURSOR 操作。这种方式与从命令行执行 LOAD FROM CURSOR 操作的差异如下:

  不需要通过执行 DECLARE CURSOR 单独定义所需的游标。在 LOAD 命令中提供相应的 SELECT 语句,就会隐式地定义游标。只有在 ADMIN_CMD 调用中嵌入 LOAD FROM CURSOR 操作的情况下,这种语法才是有效的,在命令行上是无效的。

  在 LOAD 命令中通过 DATABASE 选项定义远程数据库。不可能指定远程访问所需的用户名/密码组合。请在测试存储过程时观察这一限制的影响。

  但是,首先应该在目标数据库 MYSAMPLE 中创建存储过程。

  清单 19. 创建示例存储过程

C:\>db2 "CONNECT TO MYSAMPLE"

  
Database Connection Information

  
Database server = DB2/NT 9.5.2

  SQL
authorization ID = FECHNER

  Local
database alias = MYSAMPLE

  C:\
>db2 -tf create_load_routine.sql

  DB20000I The SQL command completed successfully.


  第一个测试调用失败,返回消息 SQL30082N Security processing failed with reason "3" ("PASSWORD MISSING"). SQLSTATE=08001。

  清单 20. 对示例存储过程的第一次测试失败 

C:\>db2 "CALL FECHNER.REMOTE_LOAD_FROM_CURSOR"

  SQL30082N Security processing failed
with reason "3" ("PASSWORD MISSING").

  SQLSTATE
=08001

  C:\
>db2 "TERMINATE"

  DB20000I The TERMINATE command completed successfully.


  这个错误消息是由于建立数据库连接的方式造成的:db2 "CONNECT TO MYSAMPLE"。在执行 CONNECT 语句时,没有提供用户名和密码,因此使用登录操作系统所用的用户名建立连接。在这种情况下,DB2 不知道此用户的密码。在存储过程中执行 LOAD FROM CURSOR 操作时,DB2 尝试用本地用户的授权 ID 连接远程数据库 SAMPLE。但是,由于使用隐式的 CONNECT,DB2 不知道相应的密码,所以远程访问失败。因此,这个错误的原因如下:

  因为通过 ADMIN_CMD 执行的 LOAD FROM CURSOR 操作不允许指定远程访问所用的用户,所以 LOAD 操作自动地用属于本地数据库连接的授权 ID 连接远程数据库。

  如果本地连接的用户执行隐式的 CONNECT 而没有指定密码,DB2 就不知道他/她的密码,因此在尝试连接远程数据库时没有密码可用。

  通过 ADMIN_CMD 执行的远程 LOAD FROM CURSOR 操作的这一特点(无法指定远程访问所用的用户)还有一个影响:当前连接本地数据库的用户必须用相同的授权 ID 访问远程数据库。在使用联邦方法访问远程数据库时,没有这一限制,因为必须以用户映射的形式定义额外的抽象层。

  既然找到了错误的原因,就可以重新连接本地数据库,这一次显式地指定用户名和密码。对存储过程的第二次调用应该会成功 (Return Status = 0),见清单 21。

  清单 21. 对示例存储过程的第二次测试成功

C:\>db2 "CONNECT TO MYSAMPLE USER fechner"

  Enter
current password for fechner:

  
Database Connection Information

  
Database server = DB2/NT 9.5.2

  SQL
authorization ID = FECHNER

  Local
database alias = MYSAMPLE

  C:\
>db2 "CALL FECHNER.REMOTE_LOAD_FROM_CURSOR"

  
Return Status = 0

  C:\
>db2 "TERMINATE"

  DB20000I The TERMINATE command completed successfully.


   结束语

  本文通过示例场景演示了如何使用 DB2 的 LOAD FROM CURSOR 特性在一个数据库中以及不同的数据库之间快速轻松地复制数据。还解释了通过 ADMIN_CMD 存储过程在应用程序代码中执行 LOAD FROM CURSOR 操作时的特殊问题。另外,还讲解了如何为另一个数据库配置联邦访问,从而像访问本地表或视图一样透明地读写远程数据库中的表和视图。

0
相关文章