procedure new_cust (p_practiceid varchar2)is
custid varchar2(255);
l_error_stack varchar2(4000);
l_error_code integer;
cursor c1 is select id
from customers
where joining_date = to_char(sysdate,'YYYY-MM');
begin
OPEN c1;
loop
FETCH c1 INTO custid;
EXIT WHEN c1%NOTFOUND;
begin
execute immediate 'drop table new_clients';
execute immediate 'create table new_clients as select * from client_names where custid= '''||custid||'''';
exception when others then
l_error_stack := substr(dbms_utility.format_error_backtrace,1,2500)||chr(10)||substr(dbms_utility.format_error_stack,1,500) ;
l_error_code := sqlcode;
daily_check_log.logger(systimestamp, inPracticeId, 'error', 'new_cust', l_error_code, l_error_stack);
end;
END LOOP;
CLOSE c1;
end;
我正在使用游标来确定本月加入的新客户端。应该至少有10条新记录,但光标只返回1行。我哪里错了?
答案 0 :(得分:1)
您不必为此简单任务创建游标,此代码应该可以满足您的要求
procedure new_cust (p_practiceid varchar2) is
begin
execute immediate 'drop table new_clients';
execute immediate 'create table new_clients as
select cn.*
from client_names cn
join customers c
on c.id = cn.custid
where c.joining_date = to_char(sysdate,''YYYY-MM'')';
end;
并且不要忘记将异常处理放入其中:)
答案 1 :(得分:0)
在我看来,整个概念都是错误的。在Oracle中,您不能动态创建表,实际上,真正罕见的情况证明了这一点。您的代码完全是静态,没有什么需要动态SQL。
考虑创建一次表 - 并根据需要重用它。它可能涉及从中删除行。
具有 false 条件的CTAS将创建一个空表:
create table new_clients as select * from client_names where 1 = 2;
每月将数据插入其中(就像您的代码所暗示的那样):
insert into new_clients
select *
from client_names
where custid in (select id
from customers
where joining_date between trunc(sysdate, 'mm')
and trunc(last_day(sysdate))
);
我认为JOINING_DATE并非YYYY-MM,而是 true 日期。如果有一个索引,它仍然可以工作,因为BETWEEN子句获取整个当月(但是,它可能需要进一步调整,具体取决于您拥有的数据)。
另外,如果你指定INSERT语句中涉及的列名称会更好(如果有很多这些名称并不重要 - 将它们命名为all,all,逐个)。 <{1}}可以正常工作,直到某些内容发生变化,然后才能正常工作。
如果需要,可以轻松地将select *
移动到程序中。说到:IN参数用于什么?你声明了它,但它从未使用过。