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

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>

Related

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>

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>

Use cursor in LOOP in new QUERY

"I missing the forest through the trees..."
I want to query each column of a table which I retrieve in a FOR LOOP, but the inner query doesn't return the right thing.
Seems that the inner query not use the current column_name.
DECLARE
v_max_TS TIMESTAMP;
BEGIN
FOR cols IN (SELECT column_name FROM all_tab_cols WHERE table_name = '<tablename>')
LOOP
SELECT
MAX(CURR_TIMESTAMP) INTO v_max_TS
FROM <tablename>
WHERE cols.column_name IS NOT NULL
ORDER BY TO_TIMESTAMP(CURR_TIMESTAMP,'MM/DD/YYYY HH24:MI:SS') DESC;
dbms_output.put_line(cols.column_name || ' ' || v_max_TS);
END LOOP;
END;
Apart from the fact that your query doesn't make much sense (as Boneist wrote as a comment), that won't work as you need to use dynamic SQL (execute immediate) for such a purpose.
Here's an example based on Scott's schema. Have a look, adjust it if necessary.
SQL> set serveroutput on
SQL> declare
2 l_str varchar2(200); -- will hold the SELECT statement
3 v_max varchar2(30);
4 begin
5 for cols in (select column_name
6 from all_tab_cols
7 where table_name = 'DEPT'
8 )
9 loop
10 l_str := 'select max(' || cols.column_name ||') from dept';
11 execute immediate l_str into v_max;
12 dbms_output.put_line(cols.column_name ||': '|| v_max);
13 end loop;
14 end;
15 /
DEPTNO: 40
DNAME: SALES
LOC: NEW YORK
PL/SQL procedure successfully completed.
SQL>

Issue with returning bulk collect . The code is thowing error

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;
...

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