DB2上的SQL,如何运行版本正确的TABLE()函数?

时间:2015-03-10 20:45:41

标签: sql db2 db2-luw

我正在为DB2编写监视器。我们有几个版本运行,9.7,10.1,10.5,我想要一个调用监视功能的监视器。它们采用" TABLE(过程(范围调用))的形式:

  • 10.5 - TABLE(mon_get_database(-1))
  • 10.1 - TABLE(snap_get_db('', - 1))
  • 9.7 - TABLE(snap_get_db_v97('', - 1))

我希望监视器针对任何版本运行并查询版本并针对它运行正确的SQL我可以拉出版本:

    SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO 
where license_installed = 'Y' fetch first row only

当我运行它时,它会正确返回:

create variable dbVersion float;
set dbVersion = (SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO
where license_installed = 'Y' fetch first row only);
select dbVersion from sysibm.sysdummy1;

例如返回9.7。当我对数据库运行9.7版本的监视器时,它可以工作:

SELECT (DAYS(current timestamp) - DAYS(last_backup)) 
        FROM sysibm.sysdummy1, TABLE(snap_get_db_v97('', -1));

返回2,这是正确的 当我尝试将它放入case语句时,它会命中第一行,错过条件,尝试执行该过程并失败:

    set dbVersion = (SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO where license_installed = 'Y' fetch first row only);
    select dbVersion from sysibm.sysdummy1; --this returns the correct version of DB2
    create variable dbCommand varchar(256);
    create variable dbBU float;
    set dbBU= 
    case
        when (SELECT PROD_RELEASE FROM SYSIBMADM.ENV_PROD_INFO 
where license_installed like 'Y') = 10.5 
then (SELECT (DAYS(current timestamp) - DAYS(last_backup))
            FROM sysibm.sysdummy1, TABLE(mon_get_database(-1)))
        when (SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO 
where license_installed = 'Y' fetch first row only) >= 10.0 
then (SELECT (DAYS(current timestamp) - DAYS(last_backup))
            FROM sysibm.sysdummy1, TABLE(snap_get_db('', -1)))
        when (SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO 
where license_installed = 'Y' fetch first row only) = 9.7 
then (SELECT (DAYS(current timestamp) - DAYS(last_backup))
            FROM sysibm.sysdummy1, TABLE(snap_get_db_v97('', -1)))
        when (SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO 
where license_installed = 'Y' fetch first row only) = 9.5 
then (SELECT (DAYS(current timestamp) - DAYS(last_backup))
            FROM sysibm.sysdummy1, TABLE(snap_get_db_v95('', -1)))
        when (SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO 
where license_installed = 'Y' fetch first row only) = 9.1 
then (SELECT (DAYS(current timestamp) - DAYS(last_backup))
            FROM sysibm.sysdummy1, TABLE(snap_get_db_v91('', -1)))
        else (SELECT (DAYS(current timestamp) - DAYS(last_backup))
            FROM sysibm.sysdummy1, TABLE(snap_get_db('', -1)))
        end;
    select dbBU ;

    commit work;

这从案例"No authorized routine named "MON_GET_DATABASE" of type "FUNCTION" having compatible arguments was found.. SQLCODE=-440, SQLSTATE=42884"返回,这是正确的,因为那是DB2 v10.5过程。

我缺少什么以及如何在DB2中执行此操作?

1 个答案:

答案 0 :(得分:1)

首先,您的代码仍然不依赖于版本。我相信,CREATE VARIABLE语句仅在v9.7之后可用。

复合SQL语句中的所有语句都将在执行之前进行编译 - DB2 SQL PL不是解释语言,因此在遇到不存在的对象时始终无法编译。您必须使用动态SQL将编译推迟到运行时,例如:

begin 
  declare st varchar(1000);
  declare rel float;

  set rel = (SELECT FLOAT(PROD_RELEASE) FROM SYSIBMADM.ENV_PROD_INFO 
      where license_installed = 'Y' fetch first row only);
  set st = 
    case
        when rel = 10.5 
        then 'SELECT (DAYS(current timestamp) - DAYS(last_backup)) FROM TABLE(mon_get_database(-1))'
        when rel >= 10.0 
        then 'SELECT (DAYS(current timestamp) - DAYS(last_backup)) FROM TABLE(snap_get_db('', -1))'
        when rel = 9.7 
        then 'SELECT (DAYS(current timestamp) - DAYS(last_backup)) FROM TABLE(snap_get_db_v97('', -1))'
        when rel = 9.5 
        then 'SELECT (DAYS(current timestamp) - DAYS(last_backup)) FROM TABLE(snap_get_db_v95('', -1))'
        when rel = 9.1 
        then 'SELECT (DAYS(current timestamp) - DAYS(last_backup)) FROM TABLE(snap_get_db_v91('', -1))'
        else 'SELECT (DAYS(current timestamp) - DAYS(last_backup)) FROM TABLE(snap_get_db('', -1))'
    end;
  prepare s from st; 
  execute s into dbBU;

end