无需查询即可检索 Oracle 数据库名称
Retrieve Oracle database name without querying
我有两个 Oracle 11gR2 数据库(一个用于测试,另一个用于生产)。
通过使用条件编译,我需要创建一个函数,该函数将在测试环境中使用数据库 link,而在生产环境中将 不 使用数据库 link。
问题是我需要把它放到包体中,它会在两种环境中自动编译。生产环境中不会有这样的数据库link,因此包不会编译。
一个解决方案是创建一个虚拟数据库 link,它在生产环境中自行解析(生产 -> 生产),但这肯定不是解决此问题的正确方法。
例如:
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;
/
包体中没有数据库 link 语法。在两种环境中创建一个同义词,并在您的包主体中引用该同义词。
这样你的包体在两种环境中都是一样的 - 只是同义词的定义不同。
如果您可以更改编译会话 - 在一个或两个环境中 - 您可以使用 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
分支。
不能将标志设置为字符串,因此不能测试特定名称;但是 true/false 对我来说似乎更直观。
如果您不能改变编译的方式来改变会话,您可以通过登录触发器来实现——在这种情况下可能只在测试环境中,并且可能使用更通用的标志名称像@krokodilko建议的env_test
。
我有两个 Oracle 11gR2 数据库(一个用于测试,另一个用于生产)。
通过使用条件编译,我需要创建一个函数,该函数将在测试环境中使用数据库 link,而在生产环境中将 不 使用数据库 link。
问题是我需要把它放到包体中,它会在两种环境中自动编译。生产环境中不会有这样的数据库link,因此包不会编译。
一个解决方案是创建一个虚拟数据库 link,它在生产环境中自行解析(生产 -> 生产),但这肯定不是解决此问题的正确方法。
例如:
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;
/
包体中没有数据库 link 语法。在两种环境中创建一个同义词,并在您的包主体中引用该同义词。
这样你的包体在两种环境中都是一样的 - 只是同义词的定义不同。
如果您可以更改编译会话 - 在一个或两个环境中 - 您可以使用 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
分支。
不能将标志设置为字符串,因此不能测试特定名称;但是 true/false 对我来说似乎更直观。
如果您不能改变编译的方式来改变会话,您可以通过登录触发器来实现——在这种情况下可能只在测试环境中,并且可能使用更通用的标志名称像@krokodilko建议的env_test
。