问题描述
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种标准方法可以做到这一点:
- 您可以使用条件编译和
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
- 要使用
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
,而不会出错。
- 要检查表/视图中是否确实存在此查询,并使用动态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