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

时间:2019-03-28 21:50:24

标签: database db2 multiple-instances

我需要比较两个不同的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的方法都是可行的。例如,如果我先连接到SECOND,然后再连接到FIRST,则第一个循环有效,第二个循环显示“ .....是未定义的名称”。如果我先执行FIRST的连接,然后执行SECOND的连接,则第一个循环将引发错误,并且没有输出。

2 个答案:

答案 0 :(得分:1)

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

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

联盟使您可以像访问本地表一样访问远程表。

如果您被禁止使用联合身份验证,则可以选择以下选项:

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

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

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

  • 如果您使用嵌入式SQL,则类型2连接提供了另一种可能性。

答案 1 :(得分:0)

在IBM i的Db2上,只能通过Db2 LUW框使用联合身份验证...

但是,以下内容在IBM i的Db2中适用...

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提取数据, trick 是在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上使用它,但是很有可能。