Procedure created with compilation errors - but can't find error - sql

I have a procedure but I can't find where the error is:
CREATE OR REPLACE PROCEDURE ADD_GRADE (
STUDEN_ID IN VARCHAR2(6),
SEC_ID IN NUMBER(6),
NEW_GRADE IN CHAR (1)
)
AS
BEGIN
UPDATE ENROLLMENT
SET grade = NEW_GRADE
WHERE s_id = STUDEN_ID AND c_sec_id = SEC_ID;
END;
/

Run this query ..
select * from user_errors where name ='ADD_GRADE'
and youll have your error

All respect goes to #MarkLeiber who spotted the error...
Try this instead:
CREATE OR REPLACE PROCEDURE ADD_GRADE (
STUDEN_ID IN VARCHAR2,
SEC_ID IN NUMBER,
NEW_GRADE IN CHAR
)
AS
BEGIN
UPDATE ENROLLMENT
SET grade = NEW_GRADE WHERE s_id = STUDEN_ID AND c_sec_id = SEC_ID;
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 );

Returning query/table into a variable

Following the instructions from here, I am trying to return the results of a query into a variable like so
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
\c test
CREATE TABLE staff(
id BIGSERIAL PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
age SMALLINT
);
CREATE FUNCTION get_contacts(
p_id_min BIGINT,
p_id_max BIGINT,
p_age_min BIGINT,
p_age_max BIGINT
)
RETURNS #contacts TABLE (
first_name VARCHAR(50),
last_name VARCHAR(50)
)
AS
BEGIN
INSERT INTO #contacts
SELECT
first_name,
last_name
FROM
staff
WHERE
id >= p_id_min
AND
id <= p_id_max;
INSERT INTO #contacts
SELECT
first_name,
last_name
FROM
staff
WHERE
age >= p_age_min
AND
age <= p_age_max;
RETURN;
END;
But I am getting the following error
DROP DATABASE
CREATE DATABASE
You are now connected to database "test" as user "postgres".
CREATE TABLE
psql:test.sql:31: ERROR: syntax error at or near "#"
LINE 5: RETURNS #contacts TABLE (
^
psql:test.sql:33: ERROR: syntax error at or near "RETURN"
LINE 1: RETURN;
^
psql:test.sql:34: WARNING: there is no transaction in progress
COMMIT
I have 2 questions:
Why am I getting the syntax error at or near "#" and how do I fix thix?
What is the significance of # at the beginning of a variable name?
Turns out, in Postgres, the RETURN command can be used multiple times, so I just did the following
CREATE FUNCTION get_contacts(
p_id_min BIGINT,
p_id_max BIGINT,
p_age_min BIGINT,
p_age_max BIGINT
)
RETURNS TABLE(
id BIGINT,
first_name VARCHAR(50),
last_name VARCHAR(50),
age SMALLINT
)
AS $$
BEGIN
--RETURN FIRST QUERY
RETURN QUERY
SELECT * FROM staff
WHERE id >=p_id_min AND id<=p_id_max;
--DO OTHER WORK
...
--RETURN SECOND QUERY
RETURN QUERY
SELECT * FROM staff
WHERE age >=p_age_min AND age<=p_age_max;
END $$ LAnguage 'plpgsql';
Author was initially using # for parameters. For code you might also try this
CREATE FUNCTION get_contacts(
p_id_min BIGINT,
p_id_max BIGINT,
p_age_min BIGINT,
p_age_max BIGINT
)
RETURNS TABLE (
first_name VARCHAR(50),
last_name VARCHAR(50)
)
AS $$
BEGIN
INSERT INTO #contacts
SELECT
first_name,
last_name
FROM
staff
WHERE
id >= p_id_min
AND
id <= p_id_max;
INSERT INTO #contacts
SELECT
first_name,
last_name
FROM
staff
WHERE
age >= p_age_min
AND
age <= p_age_max;
RETURN;
END;

Select object inside an object in PL/SQL

I have the following code:
SET SERVEROUTPUT ON
CREATE OR REPLACE TYPE work_t AS OBJECT(
company VARCHAR2(50),
salary NUMBER(5)
);
/
CREATE OR REPLACE TYPE person_t AS OBJECT(
personnum NUMBER(5),
personname VARCHAR2(20),
personwork work_t
);
/
CREATE TABLE people OF person_t(
PRIMARY KEY (personnum)
);
INSERT INTO people VALUES(12, 'George', work_t('Google',75500));
If I want to print personname:
DECLARE
per1 person_t;
BEGIN
SELECT VALUE(e) INTO per1 FROM people e WHERE e.personnum = 12;
dbms_output.put_line(per1.personname);
END;
/
Now I want to print the company (and update it in different blocks) but I don't know how to do it.
Thanks.
Just add
dbms_output.put_line(per1.personwork.company);
in
DECLARE
per1 person_t;
BEGIN
SELECT VALUE(e) INTO per1 FROM people e WHERE e.personnum = 12;
dbms_output.put_line(per1.personname);
dbms_output.put_line(per1.personwork.company);
END;
/

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

user defined functions returning multiple values in sql

I have the following tables in sql :
I want to write an function that will take Student_ID as parameter and return the Student_Name and Balance from the above table.
How can I do that ?
CREATE DEFINER=`root`#`localhost` PROCEDURE `myproc`(IN `id` INT)
NO SQL
SELECT student.Student_Name, account.Balance
FROM student INNER JOIN account
ON student.Student_ID = account.Student_ID
WHERE student.Student_ID = id
you can create procedure from phpmyadmin:
How to write a stored procedure in phpMyAdmin?
Function can be created as:
CREATE FUNCTION function_name(#Student_ID int)
RETURNS #name_and_balanceTable TABLE
(
-- Columns returned by the function_name
Name nvarchar(50),
Balance int
)
AS
-- Returns the Name and Balance for particular Student_ID
BEGIN
-- Selecting the name and balance
SELECT
#Name = st.Student_Name,
#Balance = ac.Balance
FROM Student st JOIN Account ac ON st.Student_ID = ac.Student_ID
WHERE st.Student_ID = #Student_ID;
-- Insert these value into table
BEGIN
INSERT #name_and_balanceTable
SELECT #Name, #Balance;
END;
RETURN;
END;
This is for sql-server.
For more information use this link...