I am getting an error message in Oracle SQL stored procedure - oracle

I am trying the following code
CREATE OR REPLACE PROCEDURE sal2
AS
BEGIN
SELECT sal
FROM emp
END
And I'm getting this error
Error at line 7: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
( begin case declare end exception exit for goto if loop mod
null pragma raise return select update while with
<< continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall
merge pipe purge
5. from emp
6. return 1
7. END
What I want to do is to get a sal column from emp table.

There are multiple issues with code as following;
create or replace procedure sal2
AS
Lv_var number; -- added variable for holding select value
BEGIN
select sal
Into lv_var -- into is needed in select
from emp; -- you missed this semicolon
-- you must use where clause as into variable can hold single value
-- so you must restrict this query to return only 1 record.
END; -- you missed this semicolon
/
Cheers!!

First you have to put the semicolon at the end of each line and after the END keyword. Then the SELECT statement is also wrong you have to load the result in a variable.
Here is the solution for multiple rows.
CREATE OR REPLACE PROCEDURE sal2
AS
CURSOR c_salaries IS SELECT salary FROM employees;
TYPE t_salaries IS TABLE OF c_salaries%rowtype INDEX BY BINARY_INTEGER;
v_salaries t_salaries;
BEGIN
OPEN c_salaries;
FETCH c_salaries BULK COLLECT INTO v_salaries;
CLOSE c_salaries;
END;
And one for a single row result.
CREATE OR REPLACE PROCEDURE sal2
AS
v_salary employees.salary%rowtype;
BEGIN
SELECT salary INTO v_salary
FROM employees WHERE employee_id = 100;
END;

Related

trying to add an agent (not allowing duplicate last names). Initial total sales should be zero

I am receiving the following error when trying to compile and execute. I am having issues how to figure this out.
14/7 PL/SQL: Statement ignored
14/10 PLS-00204: function or pseudo-column 'EXISTS' may be used inside a SQL statement only
Errors: check compiler log
CREATE OR REPLACE PROCEDURE AddAgent(
p_Agent_Fname IN Agent.Agent_Fname%TYPE,
p_Agent_Lname IN Agent.Agent_Lname%TYPE,
p_Agent_Address IN Agent.Agent_Address%TYPE,
p_Agent_Tsales IN Agent.Agent_Tsales%TYPE,
p_Agent_Salary IN Agent.Agent_Salary%TYPE)
IS
p_ErrorCode number; --USED FOR ERROR CHECKING
p_ErrorMsg Varchar2(200);
p_CurrentUser Varchar2(100);
BEGIN
IF EXISTS
(SELECT * FROM Agent WHERE Agent_Lname = p_Agent_Lname) THEN
dbms_output.put_line('Failure');
ELSE
INSERT INTO Agent (Agent_Fname, Agent_Lname, Agent_Address, Agent_Tsales, Agent_Salary)
SELECT p_Agent_Fname, p_Agent_Lname, p_Agent_Address, 0, p_Agent_Salary
from Dual;
COMMIT;
dbms_output.put_line('Success');
END IF;
END;
As you were told, you can't use EXISTS out of the SELECT statement. Therefore, you'll have to check for existence in the AGENT table elsewhere.
Here's one option you might consider. Note that I've also rewritten the INSERT INTO statement - there's no need to SELECT FROM DUAL, you already have all those values.
CREATE OR REPLACE PROCEDURE AddAgent(
p_Agent_Fname IN Agent.Agent_Fname%TYPE,
p_Agent_Lname IN Agent.Agent_Lname%TYPE,
p_Agent_Address IN Agent.Agent_Address%TYPE,
p_Agent_Tsales IN Agent.Agent_Tsales%TYPE,
p_Agent_Salary IN Agent.Agent_Salary%TYPE)
IS
p_ErrorCode number; --USED FOR ERROR CHECKING
p_ErrorMsg Varchar2(200);
p_CurrentUser Varchar2(100);
l_cnt number; --> newly added
BEGIN
-- check whether something exists in a table
select count(*)
into l_cnt
from dual
where exists (select null
from agent
where agent_lname = p_agent_lname
);
IF l_cnt > 0 then
dbms_output.put_line('Failure');
ELSE
INSERT INTO Agent
(Agent_Fname, Agent_Lname, Agent_Address, Agent_Tsales, Agent_Salary)
VALUES
(p_Agent_Fname, p_Agent_Lname, p_Agent_Address, 0, p_Agent_Salary);
COMMIT;
dbms_output.put_line('Success');
END IF;
END;
/

Oracle PL/SQL bad bind variable

I checked all my fields and everything is fine but i keep on getting this error
When i write this trigger on sql command it says trigger has been created but when i checked on the trigger it showed invalid
This is my trigger
create or replace trigger "Max_Crew_T1"
Before insert or update on "CREW"
for each row
declare
v_count number;
Begin
select count(*) into v_count from CREW where AirPlaneID=:NEW.AirPlaneID;
if
v_count > 5
then
Raise_Application_ERROR(-20343,'Crew number exceeded');
END IF;
END;
HERE IS THE ERROR MESSAGE;
PLS-00049: bad bind variable 'NEW.AIRPLANEID'
click on the link below for table desc
The error is because you defined the airplane id while creating the table in quotes. I.e "AirPlaneID" hence you need to do the same in the trigger.
It is not a good practice to define case-sensitive columns with quotes as it causes all these issues, its much better to define without quotes eg. create table crew (airplaneid number(6))..etc. Anyway..
Please use below:
create or replace trigger "Max_Crew_T1"
Before insert or update on "CREW"
for each row
declare
v_count number;
Begin
select count(*) into v_count from CREW where "AirPlaneID"=:NEW."AirPlaneID";
if
v_count > 5
then
Raise_Application_ERROR(-20343,'Crew number exceeded');
END IF;
END;

PL/SQL process: issue with wording

I am trying to create a page process in Oracle APEX 4.1. Specifically, When a button on this page is process submitting the page, I want this PL/SQL query to work. I don't have much of an understanding of PL/SQL and am looking to find out how to figure this issue out.
What I want the query to do:
I would like this page process to loop through each row in the EMPLOYEE table that I have in a database for APEX. For each row, I want to move the username, group and password into their own variables, and then to create an APEX user using the APEX_UTIL_CREATE_USER process. I want this to be done with every employee in the table.
I don't know specifically what is wrong with this PL/SQL, as I have never had to use it before. I would greatly appreciate any help anyone can give me with this. I will show the query and the error message below.
PL/SQL query:
PROCEDURE deploy_employee
(EMP_USERNAME IN EMPLOYEE)
IS
BEGIN
FOR indx IN NVL (EMP_USERNAME.FIRST, 0)
.. NVL (EMP_USERNAME.LAST, -1)
LOOP
emp_user EMPLOYEE.EMP_USERNAME%TYPE;
emp_pass EMPLOYEE.EMP_PASSWORD%TYPE;
emp_group EMPLOYEE.EMP_GROUP%TYPE;
BEGIN
BEGIN
select EMP_USERNAME into emp_user from EMPLOYEE;
select EMP_PASSWORD into emp_pass from EMPLOYEE;
select EMP_GROUP into emp_group FROM EMPLOYEE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
emp_user := NULL;
emp_pass := NULL;
emp_group := NUL;
END;
APEX_UTIL.CREATE_USER(
p_user_name => emp_user,
p_web_password => emp_pass,
p_user_group => emp_gorup,
);
END;
END LOOP;
END deploy_employee;
Error message:
1 error has occurred ORA-06550: line 2, column 1: PLS-00103:
Encountered the symbol "PROCEDURE" when expecting one of the
following: ( begin case declare end exception exit for goto if loop
mod null pragma raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> << continue
close current delete fetch lock insert open rollback savepoint set sql
execute commit forall merge pipe purge The symbol "declare" was
substituted for "PROCEDURE" to continue. ORA-065
The page number is 2.
Once again I would be greatly appreciative of any help I could gain.
There are multiple issues with your procedure.
You are missing the CREATE keyword, and that's the root cause for the compile time error. PLS-00103.
See the documentation for more details on CREATE PROCEDURE statement to create a standalone stored procedure or a call specification.
EMP_USERNAME IN EMPLOYEE
The data type declaration for the IN parameter is incorrect. You need to do it as:
EMP_USERNAME IN EMPLOYEE.EMP_USERNAME%TYPE
The FOR LOOP is syntactically incorrect.
FOR indx IN NVL (EMP_USERNAME.FIRST, 0) .. NVL (EMP_USERNAME.LAST, -1)
You could do it as:
SQL> CREATE OR REPLACE
2 PROCEDURE deploy_emp(
3 i_emp emp.empno%type)
4 IS
5 emp_user VARCHAR2(50);
6 BEGIN
7 FOR indx IN
8 (SELECT ename FROM emp
9 )
10 LOOP
11 BEGIN
12 BEGIN
13 SELECT ename INTO emp_user FROM emp WHERE empno = i_emp;
14 EXCEPTION
15 WHEN NO_DATA_FOUND THEN
16 emp_user := NULL;
17 END;
18 END;
19 END LOOP;
20 dbms_output.put_line(emp_user);
21 END deploy_emp;
22 /
Procedure created.
SQL> sho err
No errors.
Now, let's test it and see:
SQL> set serveroutput on
SQL> EXEC deploy_emp(7369);
SMITH
PL/SQL procedure successfully completed.
SQL>
use CREATE PROCEDURE to create a new stored procedure or EXEC <proc name> to execute it
If you whant do all this in a page process, you don't need to create procedure. Put this code in the source of your page process:
BEGIN
FOR indx IN (
select *
from EMPLOYEE
) LOOP
APEX_UTIL.CREATE_USER(
p_user_name => indx.EMP_USERNAME,
p_web_password => indx.EMP_PASSWORD,
p_user_group => indx.EMP_GROUP,
);
END LOOP;
END;

Further PL/SQL issues [duplicate]

I am trying to create a page process in Oracle APEX 4.1. Specifically, When a button on this page is process submitting the page, I want this PL/SQL query to work. I don't have much of an understanding of PL/SQL and am looking to find out how to figure this issue out.
What I want the query to do:
I would like this page process to loop through each row in the EMPLOYEE table that I have in a database for APEX. For each row, I want to move the username, group and password into their own variables, and then to create an APEX user using the APEX_UTIL_CREATE_USER process. I want this to be done with every employee in the table.
I don't know specifically what is wrong with this PL/SQL, as I have never had to use it before. I would greatly appreciate any help anyone can give me with this. I will show the query and the error message below.
PL/SQL query:
PROCEDURE deploy_employee
(EMP_USERNAME IN EMPLOYEE)
IS
BEGIN
FOR indx IN NVL (EMP_USERNAME.FIRST, 0)
.. NVL (EMP_USERNAME.LAST, -1)
LOOP
emp_user EMPLOYEE.EMP_USERNAME%TYPE;
emp_pass EMPLOYEE.EMP_PASSWORD%TYPE;
emp_group EMPLOYEE.EMP_GROUP%TYPE;
BEGIN
BEGIN
select EMP_USERNAME into emp_user from EMPLOYEE;
select EMP_PASSWORD into emp_pass from EMPLOYEE;
select EMP_GROUP into emp_group FROM EMPLOYEE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
emp_user := NULL;
emp_pass := NULL;
emp_group := NUL;
END;
APEX_UTIL.CREATE_USER(
p_user_name => emp_user,
p_web_password => emp_pass,
p_user_group => emp_gorup,
);
END;
END LOOP;
END deploy_employee;
Error message:
1 error has occurred ORA-06550: line 2, column 1: PLS-00103:
Encountered the symbol "PROCEDURE" when expecting one of the
following: ( begin case declare end exception exit for goto if loop
mod null pragma raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> << continue
close current delete fetch lock insert open rollback savepoint set sql
execute commit forall merge pipe purge The symbol "declare" was
substituted for "PROCEDURE" to continue. ORA-065
The page number is 2.
Once again I would be greatly appreciative of any help I could gain.
There are multiple issues with your procedure.
You are missing the CREATE keyword, and that's the root cause for the compile time error. PLS-00103.
See the documentation for more details on CREATE PROCEDURE statement to create a standalone stored procedure or a call specification.
EMP_USERNAME IN EMPLOYEE
The data type declaration for the IN parameter is incorrect. You need to do it as:
EMP_USERNAME IN EMPLOYEE.EMP_USERNAME%TYPE
The FOR LOOP is syntactically incorrect.
FOR indx IN NVL (EMP_USERNAME.FIRST, 0) .. NVL (EMP_USERNAME.LAST, -1)
You could do it as:
SQL> CREATE OR REPLACE
2 PROCEDURE deploy_emp(
3 i_emp emp.empno%type)
4 IS
5 emp_user VARCHAR2(50);
6 BEGIN
7 FOR indx IN
8 (SELECT ename FROM emp
9 )
10 LOOP
11 BEGIN
12 BEGIN
13 SELECT ename INTO emp_user FROM emp WHERE empno = i_emp;
14 EXCEPTION
15 WHEN NO_DATA_FOUND THEN
16 emp_user := NULL;
17 END;
18 END;
19 END LOOP;
20 dbms_output.put_line(emp_user);
21 END deploy_emp;
22 /
Procedure created.
SQL> sho err
No errors.
Now, let's test it and see:
SQL> set serveroutput on
SQL> EXEC deploy_emp(7369);
SMITH
PL/SQL procedure successfully completed.
SQL>
use CREATE PROCEDURE to create a new stored procedure or EXEC <proc name> to execute it
If you whant do all this in a page process, you don't need to create procedure. Put this code in the source of your page process:
BEGIN
FOR indx IN (
select *
from EMPLOYEE
) LOOP
APEX_UTIL.CREATE_USER(
p_user_name => indx.EMP_USERNAME,
p_web_password => indx.EMP_PASSWORD,
p_user_group => indx.EMP_GROUP,
);
END LOOP;
END;

FORALL+ EXECUTE IMMEDIATE + INSERT Into tbl SELECT

I have got stuck in below and getting syntax error - Please help.
Basically I am using a collection to store few department ids and then would like to use these department ids as a filter condition while inserting data into emp table in FORALL statement.
Below is sample code:
while compiling this code i am getting error, my requirement is to use INSERT INTO table select * from table and cannot avoid it so please suggest.
create or replace Procedure abc(dblink VARCHAR2)
CURSOR dept_id is select dept_ids from dept;
TYPE nt_dept_detail IS TABLE OF VARCHAR2(25);
l_dept_array nt_dept_detail;
Begin
OPEN dept_id;
FETCH dept_id BULK COLLECT INTO l_dept_array;
IF l_dept_array.COUNT() > 0 THEN
FORALL i IN 1..l_dept_array.COUNT SAVE EXCEPTIONS
EXECUTE IMMEDIATE 'INSERT INTO stg_emp SELECT
Dept,''DEPT_10'' FROM dept_emp'||dblink||' WHERE
dept_id = '||l_dept_array(i)||'';
COMMIT;
END IF;
CLOSE dept_id;
end abc;
Why are you bothering to use cursors, arrays etc in the first place? Why can't you just do a simple insert as select?
Problems with your procedure as listed above:
You don't declare procedures like Procedure abc () - for a standalone procedure, you would do create or replace procedure abc as, or in a package: procedure abc is
You reference a variable called "dblink" that isn't declared anywhere.
You didn't put end abc; at the end of your procedure (I hope that was just a mis-c&p?)
You're effectively doing a simple insert as select, but you're way over-complicating it, plus you're making your code less performant.
You've not listed the column names that you're trying to insert into; if stg_emp has more than two columns or ends up having columns added, your code is going to fail.
Assuming your dblink name isn't known until runtime, then here's something that would do what you're after:
create Procedure abc (dblink in varchar2)
is
begin
execute immediate 'insert into stg_emp select dept, ''DEPT_10'' from dept_emp#'||dblink||
' where dept_id in (select dept_ids from dept)';
commit;
end abc;
/
If, however, you do know the dblink name, then you'd just get rid of the execute immediate and do:
create Procedure abc (dblink in varchar2)
is
begin
insert into stg_emp -- best to list the column names you're inserting into here
select dept, 'DEPT_10'
from dept_emp#dblink
where dept_id in (select dept_ids from dept);
commit;
end abc;
/
There appears te be a lot wrong with this code.
1) why the execute immediate? Is there any explicit requirement for that? No, than don't use it
2) where is the dblink variable declared?
3) as Boneist already stated, why not a simple subselect in the insert statement?
INSERT INTO stg_emp SELECT
Dept,'DEPT_10' FROM dept_emp#dblink WHERE
dept_id in (select dept_ids from dept );
For one, it would make the code actually readable ;)

Resources