Issue with returning bulk collect . The code is thowing error - plsql

Error while executing below code. Unable to figure out the issue?
Seems like the Variable V1 is unable to hold too many values
SQL> declare
2 type T1 is table of employee%rowtype index by binary_integer;
3 V1 T1;
4 begin
5 update employee set salary=salary+500
6 where DESCRIPTION ='Tester'
7 returning first_name,last_name,salary,description
8 bulk collect into V1;
9 dbms_output.put_line ('updated # of Tester are : ' ||sql%rowcount);
10
11 for i in V1.FIRST .. V1.LAST
12 loop
13 dbms_output.put_line (V1(i).first_name || ' ' ||
14 V1(i).last_name || ' ' ||
15 V1(i).salary || ' ' ||
16 V1(i).description );
17 end loop;
18 end;
19 /
bulk collect into V1;
*
ERROR at line 8:
ORA-06550: line 8, column 21:
PL/SQL: ORA-00913: too many values
ORA-06550: line 5, column 1:
PL/SQL: SQL Statement ignored

I would love it if we could do what you're suggesting.
You're returning 4 columns, so you must specify 4 targets; unfortunately this means you'll need 4 arrays, not a single array of records.
declare
type first_names_t is table of employee.first_name%type index by binary_integer;
type last_names_t is table of employee.last_name%type index by binary_integer;
type salaries_t is table of employee.salary%type index by binary_integer;
type descriptions_t is table of employee.description%type index by binary_integer;
first_names first_names_t;
last_names last_names_t;
salaries salaries_t;
descriptions descriptions_t;
begin
update employee set salary=salary+500
where DESCRIPTION ='Tester'
returning first_name,last_name,salary,description
bulk collect into first_names,last_names,salaries,descriptions;
...

Related

how to create index by using dynamic sql?

----------- it is giving below error ,where i did mistake ---------------
declare l1 integer;
begin execute immediate q '!
begin
execute immediate ' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT(ROW_ID) PARALLEL 4 ';
execute immediate ' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT(PAR_ROW_ID, FILE_NAME, FILE_EXT, CONFLICT_ID) PARALLEL 4 ';
execute immediate '
select 1 from dual '
into :l1;
end;!' using out l1;
end;
------- error -------------------
ORA-06550: line 2, column 27:
PLS-00103: Encountered the symbol "!
begin
execute immediate " when expecting one of the following:
The issue is the incorrect q-quoting syntax. That is causing the error you're seeing.
DECLARE
BEGIN
EXECUTE IMMEDIATE q '!BEGIN NULL; END;!';
END;
/
Error report -
ORA-06550: line 3, column 23:
PLS-00103: Encountered the symbol "!BEGIN NULL; END;!" when expecting one of the following:
. ( * # % & = - + ; < / > at in is mod remainder not rem
return returning <an exponent (**)> <> or != or ~= >= <= <>
and or like like2 like4 likec between into using || multiset
bulk member submultiset
The symbol "*" was substituted for "!BEGIN NULL; END;!" to continue.
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
There should be no space between the q and the ':
DECLARE
BEGIN
EXECUTE IMMEDIATE q'!BEGIN NULL; END;!';
END;
/
PL/SQL procedure successfully completed.
How/where exactly did you run that piece of code? I tested it on TOAD and SQL*Plus in Oracle 11g.
Sample table:
SQL> CREATE TABLE s_accnt_att
2 (
3 row_id NUMBER,
4 par_row_id NUMBER,
5 file_name NUMBER,
6 file_ext NUMBER,
7 conflict_id NUMBER
8 );
Table created.
Procedure:
SQL> SET SERVEROUTPUT ON;
SQL>
SQL> DECLARE
2 l1 INTEGER;
3 BEGIN
4 EXECUTE IMMEDIATE q'[
5 begin
6 execute immediate ' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT ( ROW_ID ) PARALLEL 4 ';
7 execute immediate ' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT ( PAR_ROW_ID , FILE_NAME , FILE_EXT , CONFLICT_ID ) PARALLEL 4 ';
8 execute immediate ' select 1 from dual '
9 into :l1;
10 end;
11 ]'
12 USING OUT l1;
13
14 DBMS_OUTPUT.put_line ('L1 = ' || l1);
15 END;
16 /
L1 = 1
PL/SQL procedure successfully completed.
SQL>
Seems to be OK.
As your target database is 19c, I tried it there as well; no problem.
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
SQL> DECLARE
2 l1 INTEGER;
3 BEGIN
4 EXECUTE IMMEDIATE q'[
5 begin
6 execute immediate ' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT ( ROW_ID ) PARALLEL 4 ';
7 execute immediate ' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT ( PAR_ROW_ID , FILE_NAME , FILE_EXT , CONFLICT_ID ) PARALLEL 4 ';
8 execute immediate ' select 1 from dual '
9 into :l1;
10 end;
11 ]'
12 USING OUT l1;
13
14 DBMS_OUTPUT.put_line ('L1 = ' || l1);
15 END;
16 /
L1 = 1
PL/SQL procedure successfully completed.
SQL>
Therefore, maybe it is about your migration tool (which one is it) that doesn't recognize the q-quoting mechanism. If that's so, don't use it and double single quotes instead:
SQL> DECLARE
2 l1 INTEGER;
3 BEGIN
4 EXECUTE IMMEDIATE '
5 begin
6 execute immediate '' CREATE INDEX S_ACCNT_ATT_P1 ON S_ACCNT_ATT ( ROW_ID ) PARALLEL 4 '';
7 execute immediate '' CREATE INDEX S_ACCNT_ATT_U1 ON S_ACCNT_ATT ( PAR_ROW_ID , FILE_NAME , FILE_EXT , CONFLICT_ID ) PARALLEL 4 '';
8 execute immediate '' select 1 from dual ''
9 into :l1;
10 end;
11 '
12 USING OUT l1;
13
14 DBMS_OUTPUT.put_line ('L1 = ' || l1);
15 END;
16 /
PL/SQL procedure successfully completed.
SQL>

PLS-00201 Error in Pipelined Function in PL/SQL

I was trying to create a pipelined table function in PL/SQL but facing the below error. Is this an syntax error?
CREATE OR REPLACE FUNCTION FUNC_IDS(
IDS_IN IN VARCHAR2
) RETURN IDS_T
PIPELINED
IS
BEGIN
select * from dual;
return;
END func_ids;
Script Output:
Function FUNC_IDS compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
3/10 PLS-00201: identifier 'IDS_T' must be declared
Errors: check compiler log
I missed to create the row and table types before creating the func. Have created them later as below and trying to create the function that gets input as a string of IDs and pipe out the individual IDs to another function.
CREATE TYPE TF_ROW AS OBJECT (ID NUMBER);
CREATE TYPE IDS_T IS TABLE OF TF_ROW;
create or replace function func_ids (ids_in in varchar2) return ids_t pipelined is
n_start pls_integer := 1;
n_end pls_integer := 1;
--
begin
loop
-- find the first and next comma in string
n_start := instr(ids_in, ',', n_start, 1);
n_end := instr(ids_in, ',', n_start, 2);
--
if (n_end <= 0) then
exit;
end if;
-- get the string and pipe it back out
pipe row (to_number(substr(ids_in, n_start+1, n_end - n_start - 1)));
-- ready for next one
n_start := n_end;
end loop;
return;
end func_ids;
Script Output:
Function FUNC_IDS compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
22/5 PL/SQL: Statement ignored
22/15 PLS-00382: expression is of wrong type
Errors: check compiler log
What's wrong with the expression here?pipe row (to_number(substr(ids_in, n_start+1, n_end - n_start - 1)));
As you were told, IDS_T isn't declared.
Here's an example which works. See how I did it, do it yourself with your data.
Types:
SQL> create or replace type t_row is object (empno number, ename varchar2 (20));
2 /
Type created.
SQL> create or replace type t_tab is table of t_row;
2 /
Type created.
Function:
SQL> create or replace function func_ids (ids_in in varchar2)
2 return t_tab
3 pipelined
4 is
5 begin
6 for cur_r in (select empno, ename
7 from emp
8 where deptno = ids_in)
9 loop
10 pipe row (t_row (cur_r.empno, cur_r.ename));
11 end loop;
12
13 return;
14 end func_ids;
15 /
Function created.
Testing:
SQL> select * from table(func_ids (20));
EMPNO ENAME
---------- --------------------
7369 SMITH
7566 JONES
7788 SCOTT
7876 ADAMS
7902 FORD
SQL>
How to use the result returned by FUNC_IDS? I'm doing it using code you posted as a comment (the FUNC_ENAME function); I marked what you did wrong.
SQL> CREATE OR REPLACE FUNCTION func_ename (ids t_tab)
2 RETURN VARCHAR2
3 IS
4 l_tmp VARCHAR2 (100);
5 l_result VARCHAR2 (400);
6 BEGIN
7 l_result := ';';
8
9 FOR i IN ids.FIRST .. ids.LAST
10 LOOP
11 SELECT l.ename
12 INTO l_tmp
13 FROM emp l
14 WHERE l.empno = ids (i).empno; --> this line was wrong
15
16 l_result := l_result || l_tmp || ';';
17 END LOOP;
18
19 RETURN l_result;
20 END;
21 /
Function created.
SQL> SELECT func_ename (func_ids (10)) FROM DUAL;
FUNC_ENAME(FUNC_IDS(10))
------------------------------------------------------------------
;CLARK;KING;MILLER;
SQL>

ERROR at line 6: PL/SQL: SQL Statement ignored

I am getting an error at line 6: PL/SQL: SQL Statement ignored.
The line with "select count(*) into ecount" gives the error.
Could anyone help me?
My code:
create or replace function empcount(department in table_employee.dept_name%type)
return integer
as
ecount integer;
begin
select count(*) into ecount
from table_employee
where table_employee.dept_name=deparment and salary>500000;
return ecount;
end;
What is obvious is this: department vs. deparment:
create or replace function empcount(department in table_employee.dept_name%type)
^^^^^^^^^^
vvvvvvvvv
where table_employee.dept_name =deparment and salary>500000;
Apart from that, should be OK:
SQL> create or replace function empcount
2 (department in table_employee.dept_name%type)
3 return integer
4 as
5 ecount integer;
6 begin
7 select count(*) into ecount
8 from table_employee
9 where table_employee.dept_name = department --> fixed
10 and salary > 50000;
11 return ecount;
12 end;
13 /
Function created.
SQL> select empcount(20) from dual;
EMPCOUNT(20)
------------
2
SQL>

query to count the table rows using execute immediate

Write a function named get_total_records, to pass the table name as a parameter, and get back the number of records that are contained in the table.
Please test your function with multiple tables.
Which database is it? If Oracle, here's one option:
SQL> CREATE OR REPLACE FUNCTION get_total_records (par_table_name IN VARCHAR2)
2 RETURN NUMBER
3 IS
4 retval NUMBER;
5 BEGIN
6 EXECUTE IMMEDIATE
7 'select count(*) from ' || DBMS_ASSERT.sql_object_name (par_table_name)
8 INTO retval;
9
10 RETURN retval;
11 END;
12 /
Function created.
SQL> SELECT get_total_records ('emp') result FROM DUAL;
RESULT
----------
14
SQL> SELECT get_total_records ('dept') result FROM DUAL;
RESULT
----------
4
SQL> SELECT get_total_records ('does_not_exist') result FROM DUAL;
SELECT get_total_records ('does_not_exist') result FROM DUAL
*
ERROR at line 1:
ORA-44002: invalid object name
ORA-06512: at "SYS.DBMS_ASSERT", line 383
ORA-06512: at "SCOTT.GET_TOTAL_RECORDS", line 6
SQL>

Errors in triggers

This is my trigger:
CREATE OR REPLACE TRIGGER trg_CheckStaffID
BEFORE INSERT ON ASSIGN
FOR EACH ROW
BEGIN
DECLARE id integer := 0;
SET id := (select count(*) from (select staffid from staff where staffid ='T2');
IF (id=0) THEN
RAISE_APPLICATION_ERROR(-20000,'Please Enter A Valid Staff ID');
END IF;
END;
/
And this is the error message I get:
PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:
( - + case mod new not null
continue avg count current exists max min prior sql stddev
sum variance execute forall merge time timestamp interval
date
pipe
PLS-00103: Encountered the symbol "IF"
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
end not pragma final instantiable order overriding static
member constructor map
Invalid syntax on different places; DECLARE section should be before BEGIN. There's no SET command in PL/SQL.
Here's code that compiles; whether it does what you meant, can't tell. (I'm creating dummy tables, just to make sure that trigger creation wouldn't fail).
SQL> create table assign (id number);
Table created.
SQL> create table staff (staffid varchar2(2));
Table created.
SQL> create or replace trigger trg_checkstaffid
2 before insert on assign
3 for each row
4 declare
5 id integer := 0;
6 begin
7 select count(*)
8 into id
9 from (select staffid
10 from staff
11 where staffid ='T2');
12
13 if id = 0 then
14 raise_application_error(-20000, 'Please Enter A Valid Staff ID');
15 end if;
16 end;
17 /
Trigger created.
SQL>

Resources