How to use sql in procedure - sql

CREATE TABLE emp_table_001
(
emp_id NUMBER(10) PRIMARY KEY,
emp_name VARCHAR2(50)
);
INSERT INTO emp_table_001 VALUES(1,'addeesh');
INSERT INTO emp_table_001 VALUES(2,'arunkumar');
INSERT INTO emp_table_001 VALUES(3,'ashok');
INSERT INTO emp_table_001 VALUES(4,'bharath');
INSERT INTO emp_table_001 VALUES(5,'durairaj');
select * from emp_table_001
CREATE OR REPLACE PROCEDURE proc_1(employee_id IN NUMBER)
IS
employee_name VARCHAR2(50);
BEGIN
SELECT emp_name INTO employee_name FROM emp_table_001
WHERE emp_id = employee_id;
DBMS_OUTPUT_LINE('NAME:'||emp_name);
END;
I having trouble with the above code. Error message is this
Errors: PROCEDURE PROC_1
Line/Col: 8/1 PL/SQL: Statement ignored
Line/Col: 8/27 PLS-00201: identifier 'EMP_NAME' must be declared

The procedure should look like this:
CREATE OR REPLACE PROCEDURE proc_1 (employee_id IN NUMBER)
IS
employee_name emp_table_001.emp_name%TYPE;
BEGIN
SELECT emp_name
INTO employee_name
FROM emp_table_001
WHERE emp_id = employee_id;
DBMS_OUTPUT.PUT_LINE ('NAME:' || employee_name); --> this was wrong
END;

Related

Procedure to insert data if not exist pl sql

I have a table with these columns (id,first_name,birth). I want to create a procedure that insert a new customer only if the id inserted doesn't exist in the table. If it already exist, then don't insert it. This is my code so far, but I got an error 'line 3 sql statement ignored'. Any idea? I need to use procedure and pl sql in oracle. Thanks!
CREATE OR REPLACE PROCEDURE add_emp(v_id IN int,
v_name IN varchar2,
v_bday IN date) IS
BEGIN
INSERT INTO Employees
(Id, First_name, Birth)
SELECT *
FROM (SELECT v_id, v_name, v_bday) AS tmp
WHERE NOT EXISTS (SELECT Id FROM Employees WHERE Id = v_id);
END;
/
DECLARE
m_id int := 3;
m_name varchar2 := 'John';
m_bday date := '16-Dec-1990';
BEGIN
add_cust(m_id, m_name, m_bday);
END;
/
Your procedure has some syntax issue which is fixed in following code:
CREATE OR REPLACE PROCEDURE ADD_EMP (
V_ID IN INT,
V_NAME IN VARCHAR2,
V_BDAY IN DATE
) IS
BEGIN
INSERT INTO EMPLOYEES (
ID,
FIRST_NAME,
BIRTH
)
SELECT V_ID,
V_NAME,
V_BDAY
FROM DUAL -- FROM clause was missing
WHERE NOT EXISTS (
SELECT ID
FROM EMPLOYEES
WHERE ID = V_ID
);
END;
/
Also, Your calling PL/SQL block has some issues which are corrected in the following code:
DECLARE
M_ID INT := 3;
M_NAME VARCHAR2(10) := 'John'; -- varchar2 must be declared with size
M_BDAY DATE := DATE '1990-12-16'; -- added date literal to convert string to date
BEGIN
ADD_CUST(M_ID, M_NAME, M_BDAY);
END;
/
In Oracle SELECT does not work without a FROM clause (other DBMS products are different). So you need to provide a table; you can use DUAL, which is a dummy table provided by Oracle which is guaranteed to return one row.
INSERT INTO Employees(Id,First_name,Birth)
SELECT v_id, v_name, v_bday
from dual
WHERE NOT EXISTS (
SELECT Id FROM Employees WHERE Id = v_id
);
Your INSERT statement would work with a slight change
CREATE OR REPLACE PROCEDURE add_emp(v_id Employees.Id%type,
v_name Employees.First_name%type,
v_bday Employees.Birth%type) IS
BEGIN
INSERT INTO Employees
(Id, First_name, Birth)
SELECT v_id, v_name, v_bday
FROM dual
WHERE NOT EXISTS (SELECT * FROM Employees WHERE Id = v_id);
END;
/
You can replace INSERT statement with MERGE as an alternative DML such as
MERGE INTO Employees e1
USING
(SELECT v_id AS id, v_name AS First_name, v_bday AS birth
FROM dual) e2
ON ( e1.id = e2.id )
WHEN MATCHED THEN UPDATE SET e1.First_name = e2.First_name,
e1.Birth = e2.Birth -- If you need to change for the matching case
WHEN NOT MATCHED THEN INSERT( e1.id, e1.First_name, e1.birth )
VALUES( e2.id, e2.First_name, e2.birth );

How to use GROUP function (MAX) in FUNCTION?

CREATE TABLE cursor_table(
emp_id NUMBER(10) PRIMARY KEY,
emp_name VARCHAR2(30),
emp_salary NUMBER(5)
);
INSERT INTO cursor_table VALUES(101,'addeesh',25000);
INSERT INTO cursor_table VALUES(102,'arunkumar',28000);
INSERT INTO cursor_table VALUES(103,'ashokkumar',35000);
INSERT INTO cursor_table VALUES(104,'durairaj',22000);
CREATE OR REPLACE FUNCTION high_payed_emp
RETURN NUMBER
IS
high_payed_emp_id NUMBER(10):=0;
DECLARE max_emp_salary = MAX(emp_salary);
BEGIN
SELECT emp_id INTO high_payed_emp_id
FROM cursor_table
WHERE emp_salary = max_emp_salary;
RETURN high_payed_emp_id;
END;
I need to create a function that will find the highest paid employee.
Error message: Encountered the symbol "DECLARE" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior
You need a SQL statement to use your MAX function.
CREATE OR REPLACE FUNCTION high_payed_emp
RETURN NUMBER
IS
high_payed_emp_id NUMBER(10):=0;
max_emp_salary NUMBER :=0;
BEGIN
SELECT MAX(emp_salary)
INTO max_emp_salary
FROM cursor_table;
SELECT emp_id INTO high_payed_emp_id
FROM cursor_table
WHERE emp_salary = max_emp_salary;
RETURN high_payed_emp_id;
END;
Please check the code below, you had both syntactical and logical errors.
CREATE OR REPLACE FUNCTION high_payed_emp
RETURN NUMBER
IS
high_payed_emp_id NUMBER(10):=0;
BEGIN
select emp_id
into high_payed_emp_id
from (
select emp_id
from cursor_Table
order by emp_salary desc
)
where rownum = 1;
RETURN high_payed_emp_id;
END;
Just use the subquery to compare max salary, your code should look like this:
CREATE OR REPLACE FUNCTION high_payed_emp
RETURN NUMBER
IS
high_payed_emp_id NUMBER(10);
BEGIN
SELECT emp_id INTO high_payed_emp_id
FROM cursor_table
WHERE emp_salary = (Select max(emp_salary) from cursor_table);
RETURN high_payed_emp_id;
END;
Execution:
Select high_payed_emp from dual;
OUTPUT:
HIGH_PAYED_EMP
--------------
103

How to select into varray in Oracle

I'm trying to save a set of ids in array:
create or replace type vrray_4 as varray(4) of varchar2(10);
create or replace procedure get_acl_owner_exchange (id in varchar2 ) is
path_count int;
acl_type out vrray_4;
begin
select owner_id into acl_type from kmc_acl_perm
where permission_name = 'read.'
or permission_name = 'write.'
or permission_name = 'delete.';
end get_acl_owner_exchange;
I'm getting the error:
LINE/COL ERROR
-------- --------------------------------------------------------------------------------
3/17 PLS-00103: Encountered the symbol "VRRAY_4" when expecting one of the following:
:= . ( # % ; not null range default character
The symbol ":=" was substituted for "VRRAY_4" to continue.
You have the OUT parameter in the wrong place and you need to use BULK COLLECT INTO rather than just INTO:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE KMC_ACL_PERM(
owner_id VARCHAR2(10),
permission_name VARCHAR2(10)
)
/
CREATE OR REPLACE TYPE vrray_4 AS VARRAY(4) OF VARCHAR2(10)
/
create or replace PROCEDURE GET_ACL_OWNER_EXCHANGE (
id IN VARCHAR2,
acl_type OUT VRRAY_4
) IS
BEGIN
SELECT owner_id
bulk collect into acl_type
from KMC_ACL_PERM
where permission_name IN ( 'read.', 'write.', 'delete.' );
END GET_ACL_OWNER_EXCHANGE;
/
Does this work for you:
CREATE OR REPLACE TYPE vrray_4 AS VARRAY(4) OF VARCHAR2(10);
/
CREATE TABLE kmc_acl_perm (
owner_id VARCHAR2(10),
permission_name VARCHAR2(10)
);
CREATE OR REPLACE PROCEDURE get_acl_owner_exchange (id IN VARCHAR2) IS
path_count NUMBER;
acl_type vrray_4;
BEGIN
SELECT owner_id BULK COLLECT INTO acl_type
FROM kmc_acl_perm
WHERE permission_name IN ('read.', 'write.', 'delete.');
END get_acl_owner_exchange;
/

Check if there is a location_id and manager_id with the same name (they are from different tables)

So on that code I checked the uniqueness of department_id and department_name. Now I would like to do the same with manager_id and locations_id. Please keep in mind that manager_id is from table EMPLOYEES and locations_id is from table LOCATIONS.
I wonder if I can just continue that statement:
upper(s.department_id) = upper(d.department_id)
OR upper(s.department_name) = upper(d.department_name)
But I think that will not be enough, because it will check only in the DEPARTMENTS table. Not from LOCATIONS and EMPLOYEES like I want. Please advise.
CREATE OR REPLACE PROCEDURE add_dep(p_id NUMBER,
p_name VARCHAR2,
p_mgr NUMBER,
p_loc NUMBER) IS
BEGIN
MERGE INTO departments d
USING (
SELECT
p_id department_id,
p_name department_name,
p_mgr manager_id,
p_loc location_id
FROM dual) s
ON ( upper(s.department_id) = upper(d.department_id)
OR upper(s.department_name) = upper(d.department_name))
WHEN NOT MATCHED THEN
INSERT VALUES (s.department_id, s.department_name, s.manager_id, s.location_id);
IF SQL%ROWCOUNT = 0 THEN
INSERT INTO error_depa VALUES (p_id, p_name, p_mgr, p_loc);
END IF;
END;
EDIT - additional information
I got an error that there are not enough values for LOCATIONS and EMPLOYEES table. But I also tried to make this with exception and no_data_found. Can you modify this code and help me with that please? I would like to check the same for locations_id and manager_id.
create or replace procedure add_de(
p_id NUMBER,
p_name VARCHAR2,
p_mgr NUMBER,
p_loc NUMBER
)
is
v_dummy number;
begin
select 1
into v_dummy
from departments
where department_name = p_name OR DEPARTMENT_ID = p_id ;
insert
into error_depa
values(
p_id,
p_name,
p_mgr,
p_loc
);
exception
when no_data_found
then
insert
into departments
values(
p_id,
upper(p_name),
p_mgr,
p_loc
);
end;
I think that you want something like this:
CREATE OR REPLACE PROCEDURE add_dep(p_id NUMBER,
p_name VARCHAR2,
p_mgr NUMBER,
p_loc NUMBER) IS
BEGIN
MERGE INTO departments d
USING (
SELECT
p_id department_id,
p_name department_name,
p_mgr manager_id,
p_loc location_id
FROM dual) s
ON ( upper(s.department_id) = upper(d.department_id)
OR upper(s.department_name) = upper(d.department_name))
WHEN NOT MATCHED THEN
***INSERT(department_id, department_name,manager_id,location_id)*** VALUES (s.department_id, s.department_name, s.manager_id, s.location_id);
COMMIT;
MERGE INTO employees trg
USING (
SELECT
*
FROM employees
where
manager_id = p_mgr) src
ON ( upper(trg.manager_id) = upper(src.manager_id))
WHEN NOT MATCHED THEN
***INSERT(department_id, ...)*** VALUES (src.department_id, ....);
COMMIT;
MERGE INTO locations trg
USING (
SELECT
*
FROM locations
where
locations_id = p_loc) src
ON ( upper(trg.locations_id) = upper(src.locations_id))
WHEN NOT MATCHED THEN
***INSERT(locations_id, ...)*** VALUES (src.locations_id, ....);
COMMIT;
IF SQL%ROWCOUNT = 0 THEN
INSERT INTO error_depa VALUES (p_id, p_name, p_mgr, p_loc);
END IF;
END;
/

PL/SQL creating a trigger problems

I have to create a trigger on an Employee table. If an INSERT or UPDATE statement is issued for the Employee table the trigger launches and makes sure that the value of 'salary' field meets the criteria in the job_min_sal table. After trying over and over I got a mutating table error and now am very frustrated and don't know what to do.
JOB_MIN_SALARY TABLE:
JOB VARCHAR2(50) PRIMARY KEY
MIN_SAL NUMBER(7,2) NOT NULL
The JOB_MIN_SAL table is populated with a variety of job titles and salaries. I am confused working with my trigger and wondering if I could get some assistance where to go from here
CREATE OR REPLACE TRIGGER employee_job_salary
BEFORE INSERT OR UPDATE OF SALARY on employee
FOR EACH ROW
DECLARE
v_salary NUMBER;
BEGIN
SELECT minimum_salary
INTO v_salary
FROM job_min_salary
WHERE UPPER(job) = UPPER(:NEW.job);
I know I am really far off I am just looking for help as for what this requires and what steps I need to take to get this. Thanks!
The EMPLOYEE table:
(
EMPLOYEE_ID NUMBER(4)
EMPLOYEE_NAME VARCHAR2(20)
JOB VARCHAR2(50)
MANAGER_ID NUMBER(4)
HIRE_DATE DATE
SALARY NUMBER(9)
COMMISION NUMBER(9)
DEPARTMENT_ID NUMBER(4)
);
i am supposing you are doing something like
comparing new salary with min salary criterion and update only if :new.SALARY >= v_salary
what are you doing if this is not met, are u trapping an exception or just ignoring the error or returning an error code to debug.
post more info
CREATE TABLE job_min_salary
(
job VARCHAR2(50) PRIMARY KEY,
min_sal NUMBER(7,2) NOT NULL
);
INSERT INTO job_min_salary VALUES('CEO','100');
-- 1 rows inserted.
CREATE TABLE employee
(
employee_id NUMBER(4),
employee_name VARCHAR2(20),
job VARCHAR2(50),
manager_id NUMBER(4),
hire_date DATE,
salary NUMBER(9),
commision NUMBER(9),
department_id NUMBER(4)
);
INSERT INTO employee VALUES(1, 'Name', 'CEO', 1, TO_DATE('2000-01-01', 'YYYY-MM-DD'), 80, 80, 1);
-- 1 rows inserted.
CREATE OR REPLACE TRIGGER employee_job_salary
BEFORE INSERT OR UPDATE OF salary ON employee
FOR EACH ROW
DECLARE
v_salary NUMBER(1);
BEGIN
SELECT 1
INTO v_salary
FROM job_min_salary
WHERE UPPER(job) = UPPER(:NEW.job)
AND :NEW.salary >= min_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20999, 'Salary value is too low for given job');
END;
-- TRIGGER EMPLOYEE_JOB_SALARY compiled
SELECT * FROM employee;
-- 1 Name CEO 1 2000-01-01 00:00:00 80 80 1
UPDATE employee
SET salary = 10
WHERE job = 'CEO';
-- ORA-20999: Salary value is too low for given job
UPDATE employee
SET salary = 100
WHERE job = 'CEO';
-- 1 rows updated.
SELECT * FROM employee;
-- 1 Name CEO 1 2000-01-01 00:00:00 100 80 1