DB2 - 在 SQL PL 中查询两个数据库



我需要比较两个不同 DB2 数据库实例中的数据。我们不允许设置联合。我找到了有关如何指定来自远程数据库的数据加载的参考文献,以及有关如何指定数据库连接的参考文献,包括数据库名称、用户名等。 理想情况下,我将能够对一个数据库执行查询,然后将其与第二个数据库逐个(使用 SQL PL 循环等)进行比较,或者作为单个大型联接进行比较。我已经到了SQL PL脚本可以依次连接到每个脚本的地步(并且它会提示我输入两个密码),但是当我尝试查询表时,它只能识别第二个。

我们尝试过什么: 在开头添加两个不同的 CONNECT 语句。

声明游标并指定数据库名称(这似乎仅在从一个数据库加载到另一个数据库时才有效,我们试图避免这种情况)。

set serveroutput on@
set sqlcompat DB2@
connect to first user myname@
connect to second user myname@
-- run command: db2 -td@ -vf test3.sql
begin
declare loop_counter int;
call dbms_output.enable(100000);
set loop_counter = 0;
FIRSTLOOP: for o as ord1 cursor for 
select field1, field2 from first.firstschema.firsttable fetch first 10 rows only with ur
do
set loop_counter = loop_counter + 1;
call dbms_output.put_line('Field: '||field1||', other '||field2);
end for;
call dbms_output.put_line('End first program: ');
SECONDLOOP: for p as ord2 cursor for 
select field1, field2 from second.secondschema.secondtable fetch first 10 rows only with ur
do
set loop_counter = loop_counter + 1;
call dbms_output.put_line('Field: '||field1||', other '||field2);
end for;
call dbms_output.put_line('After second call');
end@

理想情况下,两个游标循环中的每一个将打印 10 行。实际上,无论哪个CONNECT在后面完成,都是有效的。例如,如果我先连接到第二个,然后连接到第一个,第一个循环工作,第二个循环说".....是一个未定义的名称"。如果我连接到第一个,然后连接到第二个,第一个循环抛出错误,我没有得到任何输出。

SQL PL一次只能连接到一个数据库 - 这就是设计。

在脚本示例中,第二个连接将首先关闭任何当前连接。

联合允许您像访问本地表一样访问远程表。

如果阻止您使用联合身份验证,则选项包括:

  • 在本地具体化远程表并复制数据 (这可以通过从远程光标加载来完成)。 然后,可以使用 SQL 来比较行,因为这两个表随后位于同一数据库中。 仅当您有足够的容量将两个表容纳在同一数据库中时,这才可行,尽管压缩在这里会有所帮助。

  • 不使用 SQL,而是使用其他工具 例如:根据数据量和数据类型,您可以导出源表/目标表 到平面文件并比较文件(差异等)。 还可以导出到管道并在内存比较中使用。 或者你可以使用 python 或 perl 或任何脚本语言,并在内存中以块为单位进行比较(在所有情况下) 每个线程一次只能连接到一个数据库)。

  • 使用第三方工具进行数据比较。

  • 如果使用 嵌入式 SQL,则 Type-2 Connect 提供了另一种可能性。

在 Db2 for IBM i 上,联合只能通过 Db2 LUW box 获得...

但是,以下内容在 Db2 for IBM i...

create or replace function myschema.myudtf () 
returns table (SERVER VARCHAR(18)
, as_of timestamp
, ORDINAL_POSITION INTEGER 
, JOB_NAME VARCHAR(28) 
, SUBSYSTEM VARCHAR(10) 
, AUTHORIZATION_NAME VARCHAR(10) 
, JOB_TYPE VARCHAR(3)
)
modifies SQL data
external action
not deterministic
language SQL
specific CHKAWSJOBS
begin
declare insertStmt varchar(1500);
declare global temporary table 
GLOBAL_TEMP_MY_JOBS (
SERVER VARCHAR(18)
, as_of timestamp
, ORDINAL_POSITION INTEGER 
, JOB_NAME VARCHAR(28) 
, SUBSYSTEM VARCHAR(10) 
, AUTHORIZATION_NAME VARCHAR(10) 
, JOB_TYPE VARCHAR(3)
) with replace;
for systemLoop as systemsCursor cursor for
select * from table( values ('mysys1'),('mysys2'),('mysys3')) 
as systems (server_Name)
do                                  
set insertStmt = 
' insert into GLOBAL_TEMP_MY_JOBS
select 
current_server as server, current_timestamp as as_of
, ordinal_position, job_name, subsystem, authorization_name, job_type
from table(QSYS2.ACTIVE_JOB_INFO(
SUBSYSTEM_LIST_FILTER => ''MYSBS'')) X
where exists (select 1 from ' concat server_name concat '.sysibm.sysdummy1)';
execute immediate InsertStmt;
end for;      
return select * from GLOBAL_TEMP_MY_JOBS;
end;

上面的例子比你的用例更复杂,我从远程系统上的 UDTF 中提取数据,诀窍是在 where 子句中使用 3 部分名称,这迫使数据库在远程机器上运行整个select语句;insert在本地机器上的表中。

您应该能够构建一个动态插入

set insertStmt = 'insert into lcltable
select field1, field2
from ' concat server_name concat table_name
concat ' fetch first 10 rows only with ur';

不确定这是否适用于 Db2 LUW,但很有可能。

最新更新