我正在尝试下面的动态查询,我从一个查询中获取列名,表名,我需要在变量中使用这些值,我将把它作为全局变量。
列名称可以在5到50列之间变化。 我写了下面的查询,但它不起作用。给出以下信息 匿名块完成 消息:-905-ORA-00905:缺少关键字
问题在于解析语句,DBMS_SQL.PARSE不确定要继续
DECLARE
TYPE lc_pdh_cur IS REF CURSOR;
ont_pdh lc_pdh_cur;
lv_sql_stmt VARCHAR2(3000);
lv_value VARCHAR2(1000);
lv_view_name VARCHAR2(1000);
lv_columns VARCHAR2(1000);
lv_var_columns VARCHAR2(1000);
LV_VAR_STMT VARCHAR2(1000);
LV_COL_STMT VARCHAR2(1000);
v_cursor integer;
v_dname char(20);
v_rows integer;
TYPE l_column_pair IS TABLE OF VARCHAR2(2400) -- Associative array type
INDEX BY VARCHAR2(200); -- indexed by string
l_pairs l_column_pair; -- Associative array variable
CURSOR lc_agv_name
is
SELECT database_column,decode (value_set_name,null,substr(attr_name,0,24),substr(attr_name,0,24)||'_disp') attr_name FROM ego_attrs_v a WHERE attr_group_name = 'Claims';
BEGIN
SELECT agv_name INTO lv_view_name FROM ego_attr_groups_v WHERE attr_group_name = 'Claims';
BEGIN
FOR lc_agv_name_rec in lc_agv_name
LOOP
lv_col_stmt := lv_col_stmt || lc_agv_name_rec.attr_name ||',';
lv_var_stmt := lv_var_stmt || 'l_pairs('''|| lc_agv_name_rec.database_column ||''') ,';
END LOOP;
lv_columns := SUBSTR(lv_col_stmt,0,length(lv_col_stmt)-1);
lv_var_columns := SUBSTR(lv_var_stmt,0,length(lv_var_stmt)-1);
EXCEPTION
when others
then
dbms_output.put_LINE('mESSAGE :'||lv_columns||'--'||lv_var_columns||'-'||SQLCODE||'-'||SQLERRM);
END;
BEGIN
v_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cursor, 'SELECT '||lv_columns||' INTO '||lv_var_columns|| ' FROM '||lv_view_name||' WHERE header_id = 8175', DBMS_SQL.NATIVE);
v_rows :=DBMS_SQL.EXECUTE(v_cursor);
loop
if DBMS_SQL.FETCH_ROWS(v_cursor) = 0 then
dbms_output.put_LINE('No Data :View '||lv_view_name||' Columns '||lv_columns);
exit;
end if;
end loop;
DBMS_SQL.CLOSE_CURSOR(v_cursor);
dbms_output.put_LINE('Values :'||l_pairs('Coulmn1') ||'some variable'||l_pairs('Coulmn2') );
EXCEPTION
when others
then
dbms_output.put_LINE('Message :'||lv_sql_stmt||SQLCODE||'-'||SQLERRM);
END;
END;
/
答案 0 :(得分:1)
看一下这部分
BEGIN
SELECT agv_name INTO lv_view_name FROM ego_attr_groups_v WHERE attr_group_name = 'Claims';
BEGIN
FOR lc_agv_name_rec in lc_agv_name
LOOP
lv_col_stmt := lv_col_stmt || lc_agv_name_rec.attr_name ||',';
lv_var_stmt := lv_var_stmt || 'l_pairs('''|| lc_agv_name_rec.database_column ||''') ,';
END LOOP;
lv_columns := SUBSTR(lv_col_stmt,0,length(lv_col_stmt)-1);
lv_var_columns := SUBSTR(lv_var_stmt,0,length(lv_var_stmt)-1);
EXCEPTION
when others
then
....
我认为这部分中的异常是不太可能的,这意味着你永远不会运行动态SQL的主要部分。
无论如何,这个不起作用:
DBMS_SQL.PARSE(v_cursor, 'SELECT '||lv_columns||' INTO '||lv_var_columns|| ' FROM '||lv_view_name||' WHERE header_id = 8175', DBMS_SQL.NATIVE);
你必须这样做:
TYPE l_column_pair IS TABLE OF VARCHAR2(2400) -- PL/SQL table
l_pairs l_column_pair := l_column_pair();
ColumnCount INTEGER := 0;
BEGIN
FOR lc_agv_name_rec in lc_agv_name LOOP
ColumnCount := ColumnCount + 1;
lv_col_stmt := lv_col_stmt || lc_agv_name_rec.attr_name ||',';
END LOOP;
lv_columns := SUBSTR(lv_col_stmt,0,length(lv_col_stmt)-1);
DBMS_SQL.PARSE(v_cursor, 'SELECT '||lv_columns|| ' FROM '||lv_view_name||' WHERE header_id = :headerId', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE (v_cursor, ':headerId', 8175);
FOR c_agv_name_rec in lc_agv_name LOOP
DBMS_SQL.DEFINE_COLUMN(v_cursor, lc_agv_name_rec.ROWNUM, lc_agv_name_rec.attr_name, 2400);
END LOOP;
res := DBMS_SQL.EXECUTE_AND_FETCH(v_cursor, TRUE);
FOR c in 1..ColumnCount LOOP
l_pairs.EXTEND;
DBMS_SQL.COLUMN_VALUE(v_cursor, c, l_pairs(c));
END LOOP;
DBMS_SQL.CLOSE_CURSOR(v_cursor);
注意,DBMS_SQL.EXECUTE_AND_FETCH(v_cursor, TRUE);
只提取一行(即第一行)。如果您的查询可能返回多行,则必须执行以下操作:
l_pairs.EXTEND(ColumnCount);
res := DBMS_SQL.EXECUTE(v_cursor);
WHILE (DBMS_SQL.FETCH_ROWS(v_cursor) > 0) LOOP
FOR c in 1..ColumnCount LOOP
DBMS_SQL.COLUMN_VALUE(v_cursor, c, l_pairs(c));
END LOOP;
END LOOP;