TYPE ref_cur IS REF CURSOR;
ref_cur_name ref_cur;
TYPE tmptbl IS TABLE OF ref_cur_name%ROWTYPE;
n_tmptbl tmptbl;
我尝试了这段代码,但是无法通过编译器获得它。有没有办法将ref光标的结果存储到表中?
注意 - 我需要一个表,因为我需要访问ref游标列。使用dbms_sql
来访问ref光标的记录对我来说有点困难。
更新:
/* Formatted on 8/1/2013 4:09:08 PM (QP5 v5.115.810.9015) */
CREATE OR REPLACE PROCEDURE proc_deduplicate (p_tblname IN VARCHAR2,
p_cname IN VARCHAR2,
p_cvalue IN VARCHAR2)
IS
v_cnt NUMBER;
TYPE ref_cur IS REF CURSOR;
ref_cur_name ref_cur;
v_str1 VARCHAR2 (4000);
v_str2 VARCHAR2 (4000);
v_str3 VARCHAR2 (4000);
BEGIN
v_str1 :=
'SELECT ROWID v_rowid FROM '
|| p_tblname
|| ' WHERE '
|| p_cname
|| '='''
|| p_cvalue
|| '''';
BEGIN
v_str2 :=
'SELECT COUNT ( * )
FROM '
|| p_tblname
|| ' WHERE '
|| p_cname
|| ' = '''
|| p_cvalue
|| '''';
logerrors ('proc_deduplicate',
'count exception',
SQLCODE,
v_str2 || SQLERRM,
'e');
EXECUTE IMMEDIATE v_str2 INTO v_cnt;
EXCEPTION
WHEN OTHERS
THEN
logerrors ('proc_deduplicate',
'count exception',
SQLCODE,
SQLERRM,
'e');
END;
IF v_cnt IS NOT NULL
THEN
OPEN ref_cur_name FOR v_str1;
LOOP
IF v_cnt = 1
THEN
EXIT;
ELSE
BEGIN
v_str3 :=
'DELETE FROM '
|| p_tblname
|| ' WHERE ROWID = v_rowid ';
-- THIS IS THE PROBLEM . i just created an alias above for rowid keyword but i guess, DBMS sql will have to be used after all .
EXECUTE IMMEDIATE v_str3;
EXCEPTION
WHEN OTHERS
THEN
logerrors (
' proc_deduplicate
',
' delete exception
',
SQLCODE,
SQLERRM,
' e
'
);
END;
END IF;
v_cnt := v_cnt - 1;
END LOOP;
END IF;
EXCEPTION
WHEN OTHERS
THEN
logerrors (
' proc_deduplicate',
' final exception
',
SQLCODE,
SQLERRM,
' e'
);
END;
/
答案 0 :(得分:3)
通过发出TYPE ref_cur IS REF CURSOR
,您宣布一个弱光标。弱游标不返回指定的类型。这意味着您无法声明weak_cursor%rowtype
的变量,因为弱光标不会返回任何类型。
declare
type t_rf is ref cursor;
l_rf t_rf;
type t_trf is table of l_rf%rowtype;
l_trf t_trf;
begin
null;
end;
ORA-06550: line 4, column 27:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 4, column 3:
PL/SQL: Item ignored
如果为引用游标指定返回类型,使其强大,则PL / SQL块将成功编译:
SQL> declare -- strong cursor
2 type t_rf is ref cursor return [table_name%rowtype][structure];
3 l_rf t_rf;
4 type t_trf is table of l_rf%rowtype;
5 l_trf t_trf;
6 begin
7 null;
8 end;
9 /
PL/SQL procedure successfully completed
答案 1 :(得分:2)
据我了解你在做什么,你只需要参数化删除:
...
v_str3 VARCHAR2 (4000);
v_rowid ROWID;
BEGIN
...
OPEN ref_cur_name FOR v_str1;
LOOP
FETCH ref_cur_name INTO v_rowid;
EXIT WHEN ref_cur_name%NOTFOUND;
IF v_cnt = 1
THEN
EXIT;
ELSE
BEGIN
v_str3 :=
'DELETE FROM '
|| p_tblname
|| ' WHERE ROWID = :v_rowid ';
EXECUTE IMMEDIATE v_str3 USING v_rowid;
...
您需要将ref_cur_name
提取到需要显式声明的变量中,然后将其用作删除中的绑定变量值。
您也应该对其他动态SQL中的p_cvalue
引用执行相同的操作。在单个动态语句中,您可以通过单个删除和无显式计数使这更简单:
CREATE OR REPLACE PROCEDURE proc_deduplicate (p_tblname IN VARCHAR2,
p_cname IN VARCHAR2,
p_cvalue IN VARCHAR2)
IS
BEGIN
execute immediate 'delete from ' || p_tblname
|| ' where ' || p_cname || ' = :cvalue'
|| ' and rowid != (select min(rowid) from ' || p_tblname
|| ' where ' || p_cname || ' = :cvalue)'
using p_cvalue, p_cvalue;
END proc_deduplicate;
/
如果您想知道或报告已删除的行数,可以在SQL%ROWCOUNT
之后引用execute immediate
。
答案 2 :(得分:2)
强引用游标返回定义的值,但弱对任何东西都是免费的,完全是动态的。
但我们无法在弱ref cur上定义rowtype
变量
例如
declare
refcur sys_refcursor;
emprec refcur%rowtype; --it'll yield error
,而
declare
type empref is ref cursor returns employees%rowtype;
empcur empref;
emprec empcur%rowtype; --it'll work fine.
这非常有用,现在我们可以定义它们的集合以及实际谈论的许多其他优势。
答案 3 :(得分:1)
没有。你试图在光标实例上声明类型,所以你会更接近:
TYPE tmptbl IS TABLE OF ref_cur%ROWTYPE;
但你仍然不能这样做,你会得到PLS-00310: with %ROWTYPE attribute, 'REF_CUR' must name a table, cursor or cursor-variable
。
引用游标是弱类型的,因此编译器不知道记录的样子。您可以根据块中的逻辑或动态查询打开不同结果的引用游标,编译器无法提前知道预期的内容。
%rowtype
状态record
可以应用于显式游标,强游标变量或表或视图。 PL/SQL documentation比较强和弱游标变量。
如果您知道查询的内容,则可以使用这些字段声明%rowtype
类型,如果要查询单个表,则可以声明表dbms_sql
。既然你正在使用{{1}},我想你不会知道这一点。也许如果您通过更多信息更新了您的问题,那么您可以尝试其他方法。