用DB2例程来简化迁移(1)
发表于:2007-07-13来源:作者:点击数:
标签:
简介 当使用来自于不同供应商的不同数据库系统时,用户和数据库管理员将不可避免地碰到在这些产品中各不相同的特性和功能。通常,可在以下方面发现这些差异: 受支持的 SQL 方言中的不同语法。 数据库管理器应用程序界面。 不同的管理工具及其用法。 为了使
简介
当使用来自于不同供应商的不同数据库系统时,用户和数据库管理员将不可避免地碰到在这些产品中各不相同的特性和功能。通常,可在以下方面发现这些差异:
- 受支持的 SQL 方言中的不同语法。
- 数据库管理器应用程序界面。
- 不同的管理工具及其用法。
为了使得将数据库和应用程序从 Oracle®、Sybase® 或 Microsoft® SQL Server 等数据库产品迁移到 IBM® DB2® Universal Database™(UDB)更容易,本文将展示一些可行的 DB2 UDB 功能实现,而且这些功能在其他数据库系统中也可获得。这些实现将涉及创建存储过程和用户定义函数(UDF)以实现那些常常被请求的功能。
在“下载”小节中,您将找到这些过程和函数的源代码以及包含了 CREATE PROCEDURE
和 CREATE FUNCTION
语句的 SQL 脚本。如果您对确切的实现细节很感兴趣,就请查阅这些代码。一旦编译并链接了源代码(或安装了预编译的库)以及在数据库中注册了这些过程和函数之后,您就可以按本文实例所演示的那样来使用它们了。另外值得注意的是,这些过程和函数可用于 DB2 UDB 版本 7 和版本 8。
清除表
当从 Oracle 迁移到 DB2 时,所碰到的一个普遍问题就是 TRUNCATE
命令。在 Oracle 中执行时,该命令不用借助一个或多个 DELETE
操作就可快速地清除表中所有内容, DELETE
操作需要进行大量的日志记录。
DB2 的 IMPORT
功能提供了完成相同功能的方法,只要使用 REPLACE INTO
子句以及将一个空文件指定为数据源。在该情况下,表中所有的行都将被快速清除并且只使用一条日志记录,接着就从给定的文件中导入新的数据。而对于一个空文件,就不会导入任何内容,从而在该操作结束时清除了该表。
要实现该功能,我们可以利用 DB2 定义的叫做 sqluimpr() 的 C API 函数来以程序的方式将数据导入数据库的表中。我们将这个 API 包装到存储过程中,以便可通过 SQL 接口用于所有的应用程序,而无需考虑编程的语言。清单 1 中展示了存储过程 TRUNCATE_TABLE
的签名。
清单 1. 过程 TRUNCATE_TABLE 的签名
clearcase/" target="_blank" >cccccc border=1>
>>--TRUNCATE_TABLE--(--schema_name--,--table_name--)--------><
|
VARCHAR(130)
类型的参数 schema_name 指定模式,用以在其中找到表。如果模式名外加了双引号,就将其看成定界名称(混合大小写的和特殊的字符)。如果模式名为 空
,即未指定模式,那么则要查阅 CURRENT SCHEMA
专用寄存器来确定所要使用的模式。 VARCHAR(130)
类型的参数 table_name指定将被清除的表的未限定名称。加上显式或隐式定义的模式名就可惟一地识别出表。如果表名外加了双引号,就将其看成定界名称(混合大小写的和特殊的字符)。
如果输入参数 schema_name 为 空
,则由该过程的逻辑来确定默认模式。否则,就删除现有模式名上的双引号,或者将未加引号的模式名转换为大写体。对于表名同样如此,比如最后表名上的双引号会被删除,或者未加引号的表名会被转换为大写体。接着,我们通过查询 DB2 目录视图 SYSCAT.TABLES
来证实该表是否存在。现在就可以启动导入了。先准备好必要的参数,其中使用的文件是 /dev/null(Windows 上的 NUL
文件),因为它总是存在并且不包含任何内容,也就是可用作数据源的空文件。同样,/dev/null(Windows 上的 NUL
文件)将用于进行导入所需的消息文件。如果成功地启动了导入,该过程就会成功返回。如果碰到错误,则与消息文本一起返回 SQLSTATE
以指示错误。清单 2 演示了过程 TRUNCATE_TABLE
的执行。可以在“下载”小节中找到该脚本( truncate_example.db2)的源代码。
清单 2. 测试过程 TRUNCATE_TABLE
/* create and insert some values into the table tab1 */
CREATE TABLE tab1 (col1 INTEGER NOT NULL PRIMARY KEY, col2 VARCHAR(15) )
DB20000I The SQL command completed successfully.
INSERT INTO tab1 VALUES ( 1, 'some data' ), ( 2, NULL )
DB20000I The SQL command completed successfully.
/* verify the current contents of table tab1 */
SELECT * FROM tab1
COL1 COL2
----------- ---------------
1 some data
2 -
2 record(s) selected.
/* Call the truncate stored procedure for the DB2INST1 schema, and the table tab1 */
CALL truncate('DB2INST1', 'tab1')
Return Status = 0
/* Verify that the table contents have been truncated. */
SELECT * FROM tab1
COL1 COL2
----------- ---------------
0 record(s) selected.
/* Insert some new values into the tab1 table */
INSERT INTO tab1 VALUES ( 2, 'some new data' ), ( 3, NULL )
DB20000I The SQL command completed successfully.
SELECT * FROM tab1
COL1 COL2
----------- ---------------
2 some new data
3 -
2 record(s) selected.
/* Call the truncate procedure with a NULL schema */
CALL truncate(NULL, 'tab1')
Return Status = 0
/* Verify that the table contents have been truncated. */
SELECT * FROM tab1
COL1 COL2
----------- ---------------
0 record(s) selected.
|
Sybase 的 host_name 函数
Sybase 数据库中的 host_name( ) 函数返回的是 客户机进程(非 Adaptive Server 进程)的当前主机名,也就是运行该应用程序的计算机的主机名而非数据库服务器的主机名。
清单 3 中展示了用户定义函数 HOST_NAME 的签名。
清单 3. 用户定义函数 HOST_NAME
的签名
>>--HOST_NAME--( )-------------><
|
该函数访问存储在 DBINFO
结构中的应用程序 ID 并解码客户机的 IP 地址(它是应用程序 ID 的一部分)。然后便使用 C 库函数“gethostbyaddr”来解析该 IP 地址的名称,该函数在必要时将访问名称服务器或其他源(比如 /etc/hosts)。
IP 地址是应用程序 ID 中前面 8 字节的编码,或者使用 "*LOCAL"
来代表本地连接。对于本地连接,解析的是 IP 地址为 127.0.0.1 的主机名。
清单 4 演示了 HOST_NAME
函数的执行。可以在“下载”小节中找到该脚本 host_name_example.db2 的源代码。
清单 4. 测试函数 HOST_NAME( )
下面这个例子测试演示了用以获取本地连接主机名的函数的执行。
在该场景中,DB2 数据库驻留在一个本地 AIX 机器上。
地址 127.0.0.1 在 /etc/hosts 文件中被映射到计算机名 demoaix:
/* connect to the local database */
connect to sample
Database Connection Information
Database server = DB2/6000 8.1.2
SQL authorization ID = DB2INST1
Local database alias = SAMPLE
/* execute the host_name function */
values host_name()"
1
------------------------------------------------
demoaix
1 record(s) selected.
下一个例子测试演示了远程连接上的函数的执行。
在该场景中,DB2 数据库与上面一样驻留在同一 AIX 机器上。
到 AIX 上数据库的连接是由一个 Windows 2000 客户机建立的;
该客户机的名字为 mycomputer。
/* The database samplaix is an alias for the SAMPLE database on AIX */
connect to samplaix
Database Connection Information
Database server = DB2/6000 8.1.2
SQL authorization ID = DB2INST1
Local database alias = SAMPLAIX
/* execute the host_name UDF against the remote database 鈥?
it returns the name of the computer of the client connection */
values host_name()
1
------------------------------------------------
mycomputer
|
通过触发器或用户定义函数调用存储过程的 UDF
当迁移到 DB2 时,碰到的另一个普遍问题就是其他 RDBMS 可以通过触发器或函数调用存储过程。虽然 DB2 已经承诺在未来版本中包含该功能,但是我们将展示如何使用 DB2 的当前版本来实现该功能,即通过创建一个将对存储过程发出调用的 UDF 来实现。
原文转自:http://www.ltesting.net