无需查询即可检索Oracle数据库名称

时间:2018-01-12 18:22:34

标签: database oracle plsql oracle11g conditional-compilation

我有两个Oracle 11gR2数据库(一个用于测试目的,另一个用于生产)。

通过使用条件编译,我需要创建一个在测试环境中使用数据库链接的函数,在生产中使用数据库链接。

问题是我需要将它放入包体中,它将在两种环境中自动编译。生产环境中不会有这样的数据库链接,因此包将无法编译

一种解决方案是创建一个虚拟数据库链接,在生产环境中解析为自身(生产 - >生产),但这肯定不是解决此问题的正确方法。

例如:

DECLARE 
    v_db_name     VARCHAR2(200);
    vt_tbl_data   data_table%ROWTYPE;
BEGIN
    $IF v_db_name = 'TEST' $THEN 
        SELECT tbl.*
          INTO vt_tbl_data
          FROM data_table@otherdb tbl
         WHERE ROWNUM = 1;
    $ELSIF v_db_name = 'PROD' $THEN
        SELECT tbl.*
          INTO vt_tbl_data
          FROM data_table tbl
         WHERE ROWNUM = 1;
    $END
END;
/

2 个答案:

答案 0 :(得分:4)

在包体中没有数据库链接语法。在两个环境中创建同义词,并引用包体中的同义词。

这样,您的包体在两种环境中都是相同的 - 只有同义词的定义不同。

答案 1 :(得分:2)

如果你可以改变编辑会话 - 在任一环境或两种环境中 - 你可以使用a compilation flag via PLSQL_CCFLAGS

alter session set PLSQL_CCFLAGS = 'has_db_link:TRUE';

DECLARE 
    vt_tbl_data   data_table%ROWTYPE;
BEGIN
    $IF $$has_db_link $THEN 
        SELECT tbl.*
          INTO vt_tbl_data
          FROM data_table@otherdb tbl
         WHERE ROWNUM = 1;
    $ELSE
        SELECT tbl.*
          INTO vt_tbl_data
          FROM data_table tbl
         WHERE ROWNUM = 1;
    $END
END;
/

或重复次数较少,但可能更难以遵循:

DECLARE 
    vt_tbl_data   data_table%ROWTYPE;
BEGIN
    SELECT tbl.*
      INTO vt_tbl_data
    $IF $$has_db_link $THEN 
      FROM data_table@otherdb tbl
    $ELSE
      FROM data_table tbl
    $END
     WHERE ROWNUM = 1;
END;
/

如果您将标志设置为FALSE,或者根本没有设置它,那么它只会编译$ELSE分支。

您无法将标志设置为字符串,因此无法测试特定名称;但无论如何,真/假对我来说似乎更直观。

如果您无法更改编译的发生方式以便更改会话,您可以通过登录触发器执行此操作 - 可能仅在此情况下的测试环境中,并且可能使用更通用的标记名称,如{ {1}}正如@krokodilko建议的那样。