我必须在几个Oracle服务器/实例上执行SQL。 如果Oracle版本为12G,则我要查询的表格为" foo"。如果Oracle版本为11G,则表将为" bar'
我尝试了一些事情,但是我对光标
不了解 CURSOR C1
IS
SELECT version FROM V$INSTANCE
MY_VERSION VARCHAR2 ( 500 );
BEGIN
OPEN C1;
FETCH C1
INTO
MY_QUERY;
CLOSE C1;
IF MY_QUERY like '%12.%
THEN
EXECUTE IMMEDIATE 'select * from foo';
ELSE IF MY_QUERY like '%11.%'
EXECUTE IMMEDIATE 'select * from bar';
END IF;
END;
我认为这实际上是一个非常糟糕的计划。如果版本不同,只需编写一个针对每个版本的不同过程,如果它们相同,则将表命名相同。继续执行该计划可能是一场维护噩梦,并且在以后的问题分析和解决方案中显然会如此。但是您可以通过有条件的汇编来完成此操作。示例:
CREATE OR REPLACE PROCEDURE foo_or_bar AS
$IF DBMS_DB_VERSION.VER_LE_11 $THEN
type myfoobar_t is table of bar%rowtype;
$ELSE
type myfoobar_t in table of foo%rowtype;
$END
myfoobar myfoobar_t;
BEGIN
$IF DBMS_DB_VERSION.VER_LE_11 $THEN
select *
bulk collect
into myfoobar
from bar;
$ELSE
select *
bulk collect
into myfoobar
from foo;
$END
...
end foo_or_bar;
下一个匿名子程序可以帮助您解决问题。
declare
type v_foo is table of foo%rowtype index by pls_integer;
t_foo v_foo;
type v_bar is table of bar%rowtype index by pls_integer;
t_bar v_bar;
begin
if dbms_db_version.version = 12 then
execute immediate 'select * from foo' bulk collect into t_foo;
elsif dbms_db_version.version = 11 then
execute immediate 'select * from bar' bulk collect into t_bar;
end if;
end;
另一种方法,
DECLARE
v_SQL VARCHAR2(2000);
v_instance VARCHAR2(100);
BEGIN
SELECT name INTO v_instance FROM V$database;
IF (NVL(v_instance, 'EE12C') = 'EE12C') THEN
-- 12C related script goes here
v_SQL := '';
END IF;
IF (NVL(v_instance, 'EE19C') = 'EE19C') THEN
-- 19C related script goes here
v_SQL := '';
END IF;
END;
/
我希望这对某人有帮助。
解决此问题的唯一正确方法是将一些编译器指令放入源代码中,以便将其移植到较新的版本中。这是通过使用(在Oracle版本或等于11中不支持的代码的示例(
来完成的。$如果dbms_db_version.ver_le_11 $,则在Oracle版本中或等于11 之前支持的程序的电话$ else呼叫来自Oracle版本12及向上支持的过程的电话$ end
例如,来自Oracle 18 dbms_lock.sleep 被 dbms_session.sleep 替换。因此,如果您使用dbms_lock.sleep,则需要在第18版或更高版本上替换dbms_session.sleep。通过这样做,该代码不再不再在以前的版本上运行,除非您使用编译器指令并实现这两种方法,一种用于版本,而在此之后的版本中进行。
。在此处阅读更多:Oracle DBMS_DB_Version