Sql 根据Oracle版本执行查询

Sql 根据Oracle版本执行查询,sql,oracle,plsql,Sql,Oracle,Plsql,我必须在几个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

我必须在几个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;

下一个匿名子程序可以帮助您解决问题

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
     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;

我认为这实际上是一个非常糟糕的计划。如果版本不同,只需针对每个版本编写不同的过程,如果它们相同,则将表命名为相同。继续执行此计划很可能是一场维护噩梦,在以后的问题分析和解决中也会如此。但您可以通过条件编译来实现这一点。例如:

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;

我认为这实际上是一个非常糟糕的计划。如果版本不同,只需针对每个版本编写不同的过程,如果它们相同,则将表命名为相同。继续执行此计划很可能是一场维护噩梦,在以后的问题分析和解决中也会如此。但您可以通过条件编译来实现这一点。例如:

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
    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;
/
我希望这对某人有所帮助。

另一种方法

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;
/

我希望这对其他人有所帮助。

两个表是否都存在于每个版本中?如果是这样的话,frjtorres的答案应该有效。如果这些表甚至不存在,那么您可能需要使用条件编译;所以我不能只做
desc foo
并基于它执行查询两个表在每个版本中都存在吗?如果是这样的话,frjtorres的答案应该有效。如果这些表甚至不存在,那么您可能需要使用条件编译;因此,我不能像条件编译解决方案那样,只做
desc foo
并基于iTunes执行查询。这种方法要求foo和BAR在两个数据库版本中都存在,也许是这样,问题还不清楚。但如果不是这样,则需要使用记录类型而不是
%rowtype
来定义目标变量,@APC FOO和BAR可能不存在于所有数据库中。你能提供一个记录类型的例子吗?与条件编译解决方案不同,这种方法要求FOO和BAR在两个数据库版本中都存在,也许是这样,问题还不清楚。但如果不是这样,则需要使用记录类型而不是
%rowtype
来定义目标变量,@APC FOO和BAR可能不存在于所有数据库中。你能提供一个记录类型的例子吗?