如何忽略oracle中的tab / column不存在错误?

问题描述

我有以下代码

declare
var_cdb varchar2(3);
var_eleven varchar2(2);
...
..
begin
    SELECT to_number(substr(version,1,2)) into var_eleven FROM V$INSTANCE;
if var_eleven > 11
then
    select cdb into var_cdb from v$database;
    if var_cdb = 'YES'
    then
....

但是在Oracle 11g中执行PL / sql代码时,出现以下错误

ERROR at line 12:
ORA-06550: line 12,column 9:
PL/sql: ORA-00904: "CDB": invalid identifier
ORA-06550: line 12,column 2:
PL/sql: sql Statement ignored
ORA-06550: line 15,column 43:
PL/sql: ORA-00942: table or view does not exist
ORA-06550: line 15,column 19:
PL/sql: sql Statement ignored
ORA-06550: line 17,column 248:
...

如果此版本中不存在表/列,如何忽略?我需要创建一个脚本,该脚本在11g up中成功执行,并验证数据库12c up是否为cdb,是否为pdbs

解决方法

有3种标准方法可以做到这一点:

  1. 您可以使用条件编译和dbms_db_version包:
declare
   v_version  pls_integer:= dbms_db_version.version;
   v_release  pls_integer:= dbms_db_version.release;
   
   v_version_full  varchar2(12);
   var_cdb    varchar2(3);
begin
    $IF dbms_db_version.ver_le_11 $THEN
        var_cdb := 'NO';
        select version into v_version_full from v$instance;
    $ELSE
        select cdb into var_cdb from v$database;
        select version_full into v_version_full from v$instance;
    $END
    dbms_output.put_line(v_version||'.'||v_release);
    dbms_output.put_line(v_version_full);
    dbms_output.put_line(var_cdb);
end;
/

示例从18.3输出:

18.0
18.3.0.0.0
YES
  1. 要使用xmltype(cursor({your query with *}))并解析其输出,请执行以下操作:
select 
    nvl(version_full,version) as db_version
from xmltable(
        '/'
        passing xmltype(cursor(select * from v$instance))
        columns 
            version       varchar2(12) path '/ROWSET/ROW/VERSION',version_full  varchar2(12) path '/ROWSET/ROW/VERSION_FULL'
);

因此,如果您的查询没有将version_full列返回到xml,您将在null中获得version_full,而不会出错。

  1. 要检查表/视图中是否确实存在此查询,并使用动态sql仅返回所需数据:
DECLARE
  v_sql       varchar2(32000);
  select_list varchar2(100);
  c           NUMBER;
  d           NUMBER;
  col_cnt     INTEGER;
  f           BOOLEAN;
  rec_tab     DBMS_SQL.DESC_TAB;
  col_num    NUMBER;
  val       varchar2(100);
  cursor_status  INTEGER;
  
  PROCEDURE print_rec(i int,rec in DBMS_SQL.DESC_REC) IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE(i || '. ' || rec.col_name);
    --DBMS_OUTPUT.PUT_LINE('col_type            =    ' || rec.col_type);
    --DBMS_OUTPUT.PUT_LINE('col_maxlen          =    ' || rec.col_max_len);
    --DBMS_OUTPUT.PUT_LINE('col_name            =    ' || rec.col_name);
    --DBMS_OUTPUT.PUT_LINE('col_name_len        =    ' || rec.col_name_len);
    --DBMS_OUTPUT.PUT_LINE('col_schema_name     =    ' || rec.col_schema_name);
    --DBMS_OUTPUT.PUT_LINE('col_schema_name_len =    ' || rec.col_schema_name_len);
    --DBMS_OUTPUT.PUT_LINE('col_precision       =    ' || rec.col_precision);
    --DBMS_OUTPUT.PUT_LINE('col_scale           =    ' || rec.col_scale);
    --DBMS_OUTPUT.PUT_LINE('col_null_ok         =    ' || case when rec.col_null_ok 'true' else 'false' end);
  END;
BEGIN
  c := DBMS_SQL.OPEN_CURSOR;

    select 
        listagg(column_name,',') within group(order by column_id) as select_list
        into select_list
    from all_tab_columns tc 
    where tc.owner='SYS'
    and table_name='V_$INSTANCE'
    and column_name like 'VERSION%';
    
    v_sql := 'select '|| select_list || ' from v$instance';

  DBMS_SQL.PARSE(c,v_sql,DBMS_SQL.NATIVE);
 
  d := DBMS_SQL.EXECUTE(c);
 
  DBMS_SQL.DESCRIBE_COLUMNS(c,col_cnt,rec_tab);
  for i in 1..col_cnt loop
        dbms_sql.define_column(c,i,val,100);
  end loop;
/*
 * Following loop could simply be for j in 1..col_cnt loop.
 * Here we are simply illustrating some of the PL/SQL table
 * features.
 */
  col_num := rec_tab.first;
  IF (col_num IS NOT NULL) THEN
    LOOP
      print_rec(col_num,rec_tab(col_num));
      col_num := rec_tab.next(col_num);
      EXIT WHEN (col_num IS NULL);
    END LOOP;
  END IF;

  LOOP
    cursor_status := dbms_sql.fetch_rows(c);
    for i in 1..col_cnt loop
        dbms_sql.column_value(c,val);
        DBMS_OUTPUT.PUT_LINE(rec_tab(i).col_name||':'||val);
    end loop;
    EXIT WHEN cursor_status != 100;
  END LOOP;

  DBMS_SQL.CLOSE_CURSOR(c);
END;
/

结果:

1. VERSION
2. VERSION_LEGACY
3. VERSION_FULL
VERSION:18.0.0.0.0
VERSION_LEGACY:18.0.0.0.0
VERSION_FULL:18.3.0.0.0