Я новичок в plsql и пытаюсь написать процедуру, которая подсчитывает количество записей в таблице и помещает результат в другую таблицу. Теперь есть несколько таблиц, для которых я хочу сделать это, поэтому я помещаю их в varray, но сталкиваюсь с вышеупомянутой ошибкой.
Create Or Replace Procedure count
AS
type arr IS VARRAY(5) OF VARCHAR2(30);
tables arr :=arr('tb1','tb2','tb3','tb4','tb5');
cnt NUMBER;
BEGIN
FOR i in 1 .. tables.COUNT
LOOP
select Count(*) INTO cnt from tables(i);
insert into tb6 VALUES(tables(i),cnt);
END LOOP
END;
Это была просто опечатка
Для этого вам понадобится динамический SQL.
Вот как: несколько примеров таблиц (на основе таблицы emp
Скотта) и tb6
, которые будут содержать результат:
SQL> create table tb6 (val varchar2(10), cnt number);
Table created.
SQL> create table tb1 as select * from emp where deptno = 10;
Table created.
SQL> create table tb2 as select * from emp where deptno = 20;
Table created.
SQL> create table tb3 as select * from emp where deptno = 30;
Table created.
Какой результат я ожидаю?
SQL> select deptno, count(*) from emp group by deptno order by deptno;
DEPTNO COUNT(*)
---------- ----------
10 3
20 5
30 6
Процедура:
SQL> create or replace procedure p_count as
2 type arr is varray(5) of varchar2(30);
3 tables arr := arr('tb1', 'tb2', 'tb3');
4 cnt number;
5 begin
6 for i in 1 .. tables.count loop
7 execute immediate 'select count(*) from ' || tables(i) into cnt;
8 insert into tb6 values(tables(i), cnt);
9 end loop;
10 end;
11 /
Procedure created.
Тестирование:
SQL> set serveroutput on
SQL> exec p_count;
PL/SQL procedure successfully completed.
SQL> select * from tb6;
VAL CNT
---------- ----------
tb1 3
tb2 5
tb3 6
SQL>
Как видите, содержимое tb6
соответствует ожидаемым значениям.
Спасибо за помощь, просто хотел спросить, целесообразно ли использовать динамический sql, так как это приведет к огромному снижению производительности?
Пожалуйста. Что касается динамического SQL: используйте его, если необходимо. Вы могли бы сделать то же самое, используя несколько отдельных запросов, поэтому... вам решать, по какому пути вы пойдете. Для таких простых динамических операторов я бы сказал, что это более простой подход, который легко поддерживать. Для сложных динамических операторов, которые сложно писать, отлаживать и поддерживать, стоит подумать о другом подходе.
Да, именно это кажется более простым подходом, потому что я только тестировал это на самом деле. У меня есть более 50 таблиц, для которых мне нужно это сделать, так что это означало бы написание аналогичных sql-запросов более 50 раз, если используется статический sql.
У вас есть
VAUES
неVALUES
.,END LOOP
отсутствует разделитель оператора;
. Кроме того,COUNT
— это встроенная функция, и вы должны называть ее по-другому.