我有两个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;
/
答案 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建议的那样。