Sql 可以将类型声明为ref cursor rowtype吗
我试过这段代码,但无法通过编译器。有没有办法将ref cursor的结果存储到表中 注意-我需要一个表,因为我需要访问ref cursor的列。使用Sql 可以将类型声明为ref cursor rowtype吗,sql,oracle,plsql,ref-cursor,Sql,Oracle,Plsql,Ref Cursor,我试过这段代码,但无法通过编译器。有没有办法将ref cursor的结果存储到表中 注意-我需要一个表,因为我需要访问ref cursor的列。使用dbms\u sql访问ref cursor的记录对我来说有点困难 更新: TYPE ref_cur IS REF CURSOR; ref_cur_name ref_cur; TYPE tmptbl IS TABLE OF ref_cur_name%ROWTYPE; n_tmptbl tmptbl; 通过发出TYPE
dbms\u sql
访问ref cursor的记录对我来说有点困难
更新:
TYPE ref_cur IS REF CURSOR;
ref_cur_name ref_cur;
TYPE tmptbl IS TABLE OF ref_cur_name%ROWTYPE;
n_tmptbl tmptbl;
通过发出
TYPE ref\u cur IS ref CURSOR
您正在声明一个弱游标。弱游标不返回指定的类型。这意味着您不能仅仅因为弱游标不返回任何类型而声明弱游标%rowtype
的变量
/* 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;
/
如果为ref游标指定返回类型,使其成为强类型,则PL/SQL块将成功编译:
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
不需要。您正试图针对游标实例声明类型,因此您可以更接近:
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
但您仍然无法做到这一点,您将得到PLS-00310:使用%ROWTYPE属性,“REF\u CUR”必须命名一个表、游标或游标变量
ref游标是弱类型的,因此编译器不知道记录是什么样子。根据块中的逻辑或动态查询,可以为不同的结果打开ref游标,编译器将无法提前知道预期结果
%rowtype
可应用于显式游标、strong游标变量或表或视图的状态。并比较了强游标变量和弱游标变量
如果您知道您的查询将是什么,您可以使用这些字段声明一个
记录
类型,如果您要查询单个表,则可以针对一个表声明一个%rowtype
。由于您使用的是dbms\u sql
,我想您可能不知道这一点。如果您更新了您的问题,并提供了更多关于您实际尝试执行的操作的信息,那么您可以尝试其他方法。据我所知,您只需将删除参数化即可:
TYPE tmptbl IS TABLE OF ref_cur%ROWTYPE;
您需要将ref\u cur\u name
提取到一个显然需要声明的变量中,然后将其用作delete中的绑定变量值
您也应该对另一个动态SQL中的p\cvalue
引用执行相同的操作。您可以在一条动态语句中使用一个delete,而不使用显式计数,从而简化此操作:
...
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;
...
如果您想知道或报告删除了多少行,可以在
executeimmediate
后参考SQL%ROWCOUNT
,Strong ref游标返回定义的值,但weak可以自由选择任何内容,完全是动态的
但是我们不能在弱ref cur上定义rowtype
变量
e、 g
当
这是非常有用的,现在我们可以在它们上定义集合,如果您实际讨论的话,还可以定义许多其他优点。在一行中:-
type t\u rf是ref cursor return table\u或\u structure%rowtype在我的例子中,code>table_name将在这里引用tmptbl
,即我将我的行修改为'TYPE ref\u cur IS ref CURSOR return tmptbl%rowtype`…RYT?@kushal-您试图基于ref_cur
定义tmptbl
,因此这将是一个循环依赖项,也不会起作用。所以不,它将引用一个实际的表或视图,或者您以前用强类型声明的其他内容。@Alex Poole我在这个声明上面的过程中有一个tablename作为IN参数。我可以用它吗?@kushal-不,这是一个变量字符串,不是编译器可以引用的东西。请编辑您的问题以解释您实际在做什么。到目前为止,听起来好像只有dbms\u sql
是您的唯一选择。@AlexPoole是的,事实证明dbms\u sql是唯一剩下的解决方案。我实际上是在试图避免它,因为我不知道如何实现它。无论如何,我已经更新了我的整个程序。请根据您的需要进行修改。编译时会出现此错误。PLS-00487:对变量“REF\u CUR\u NAME”的引用无效。
I love you alex。请给我一个合适的链接,介绍绑定变量的用法和示例。我刚刚学了一个,但我可能还需要更多。@kushal-对不起,把我的光标循环类型弄混了。您需要从游标中获取值,并将其作为绑定变量用在delete中。@kushal-这是,本网站和Internet上散布了许多示例。
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;
/
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.