I’m trying to create a stored procedure in Oracle apex that execute 4 other procedures that work by themselves alone, but it looks like I'm doing something wrong. And I don't really know what to change, could someone please help me?
create or replace procedure "UPDATE_COST"
is
begin
UPDATE orders
SET order_price = (
SELECT sum(total)
FROM detail_order
where detail_order.nord=orders.nord
group by nord
);
end;
create or replace procedure "Detail_quantity_proc"
is
begin
update detail_order d set
d.total = (select d.quantity * p.price_exclvat
from product p
where p.npro = d.npro
)
where exists (select null from product a
where a.npro = d.npro
);
end;
create or replace procedure "Proc_excl_vat"
is
begin
UPDATE bill
SET PRICE_EXCL_VAT = (
SELECT ORDER_PRICE
FROM orders
where orders.nord=bill.nord
);
end;
create or replace procedure "Proc_INCL"
is
begin
UPDATE BILL SET PRICE_INCL_VAT = PRICE_EXCL_VAT*1.06;
end;
create or replace procedure "Fill_all_cost"
is
begin
execute UPDATE_COST;
execute Detail_quantity_proc;
execute Proc_excl_vat;
execute Proc_INCL;
end;
You don't need the execute keyword. Also, you have those defined with double quotes, so they are case sensitive. Redefine them without the quotes:
create or replace procedure fill_all_costs
is
begin
update_cost;
detail_quantity_proc;
proc_excl_vat;
proc_incl;
end;
Related
I am writing a SQL stored procedure in Snowflake (language SQL NOT Javascript).
I am trying to save a count from a SELECT statement into a variable and the table name for the select statement needs to come from a variable.
Here is what I have so far but this is failing. I don't know where to put the USING or if I can even do this? I feel like I just don't have it syntactically correct yet.
create or replace procedure myprocedure(DBNAME varchar(16777216))
returns int
language sql
as
$$
DECLARE
excludeCount int;
fullyQualifiedProceduresTable varchar(16777216);
BEGIN
fullyQualifiedProceduresTable := CONCAT(DBNAME, '.INFORMATION_SCHEMA.PROCEDURES');
excludeCount := (SELECT count(*) as count from TABLE (?) WHERE PROCEDURE_OWNER = '<ROLE NAME>') USING fullyQualifiedProceduresTable ;
IF (excludeCount > 0) THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
$$;
This is what I got to work using slightly different syntax for using variables.
Syntax taken from here
create or replace procedure myprocedure(DBNAME varchar(16777216))
returns int
language sql
as
$$
DECLARE
excludeCount int;
fullyQualifiedProceduresTable varchar(16777216);
BEGIN
SELECT CONCAT(:DBNAME, '.INFORMATION_SCHEMA.PROCEDURES') into :fullyQualifiedProceduresTable;
SELECT count(*) into :excludeCount from IDENTIFIER(:fullyQualifiedProceduresTable) WHERE PROCEDURE_OWNER = '<role>';
IF (excludeCount > 0) THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
$$;
I am not sure why you need a procedure for this. Could you not do...
set table_name='abc';
set excludeCount=(select case when count(*)>0 then 1 else 0 end from identifier($table_name));
try this
call my_proc('bus_day');
create or replace procedure my_proc(table_name varchar)
returns table(a integer)
language sql
as
$$
declare
res RESULTSET;
query varchar default 'SELECT count(*) FROM ' || :table_name ;
begin
res := (execute immediate :query);
return table (res);
end;
$$;
I created this procedure in Oracle SQL Developer.
CREATE OR REPLACE PROCEDURE CUST_NAME_LIMIT(
I_CUSTOMER_NUM IN CUSTOMER.CUSTOMER_NUM%TYPE,
I_CUSTOMER_NAME OUT CUSTOMER.CUSTOMER_NAME%TYPE,
I_CREDIT_LIMIT OUT CUSTOMER.CREDIT_LIMIT%TYPE)
AS
BEGIN
SELECT CUSTOMER_NAME, CREDIT_LIMIT
INTO
I_CUSTOMER_NAME, I_CREDIT_LIMIT
FROM
CUSTOMER
WHERE
CUSTOMER_NAME = I_CUSTOMER_NAME;
DBMS_OUTPUT.PUT_LINE(I_CUSTOMER_NAME);
DBMS_OUTPUT.PUT_LINE(I_CREDIT_LIMIT);
END;
When I try to display the output with this below I get an error
BEGIN
CUST_NAME_LIMIT('126');
END;
It should out put
TOYS GALORE
7500
Only if you told us which error you got, instead of letting us guess. But hey, it is more fun this way!
As you declared a procedure to accept one IN and two OUT parameters:
create or replace procedure cust_name_limit(
i_customer_num in customer.customer_num%type,
i_customer_name out customer.customer_name%type,
i_credit_limit out customer.credit_limit%type)
as
begin
select customer_name, credit_limit
into i_customer_name, i_credit_limit
from customer
where customer_name = i_customer_name;
end;
you have to do the same when calling it:
declare
l_custname customer.customer_name%type;
l_credlim customer.credit_limit%type;
begin
CUST_NAME_LIMIT('126', l_custname, l_credlim);
dbms_output.put_line(l_custname ||' - '|| l_credlim);
end;
/
Displaying the result from within the procedure doesn't make much sense; do so once it returns values.
create or replace procedure sp_test as
begin
CREATE TABLE T AS SELECT col1,col2 FROM t1;
FOR N IN (SELECT * FROM T) LOOP
UPDATE t1 SET t1.col1='value' where col2='value2';
END LOOP;
drop table T;
end;
/
I need to select data into t table from a t1 table in order to apply some modifications, and merge those modifications in t1 table (origin table) before deleting table t.
I m getting this error : PLS-00103
You need to use execute immediate for any ddl inside any pl/sql block. Try the below code:
create or replace procedure sp_test
is
begin
Execute Immediate 'CREATE TABLE T AS SELECT col1,col2 FROM t1';
FOR N IN (SELECT * FROM T) LOOP
Execute immediate 'UPDATE t1 SET t1.col1=''value'' where col2=''value2''';
END LOOP;
execute immediate 'drop table T';
end;
/
Thanks everybody for your contribution, I tried something that works :
A cursor for update.
Thanks for help :)
1) Create a procedure (PrintProc) that prints out "This is the Final Test".
2) Create a procedure (UpdateProc) that takes a 'student Id' and then updates his State to ‘New York’.
Pic student database
Pic of faculty database
For #1 is it
CREATE OR REPLACE
PROCEDURE PrintProc IS
BEGIN
DBMS_OUTPUT.PUT_LINE(’This is the Final Test’);
END;
To execute I did
begin
PrintProc;
end;
but I got an error
For #2 is it
CREATE OR REPLACE PROCEDURE UpdateProc
AS
BEGIN
Update Student
set s_state = 'New York'
where s_state = 'WI'
END;
and got this error Error at line 6: PL/SQL: ORA-00933: SQL command not properly ended
to execute it is it
Begin
UpdateProc;
end;
6) Create a procedure (PrintStudentsProc) that prints out a list of students who have been taught by Kim Cox.
CREATE OR REPLACE PROCEDURE PrintStudentsProc
AS
BEGIN
Select S.S_ID, F.F_ID
FROM Faculty F INNER JOIN STUDENT S ON F.F_ID = S.F_ID
WHERE F.F_ID = 1
END;
and I get this error Error at line 4: PLS-00428: an INTO clause is expected in this SELECT statement
Was about to make another topic about triggers but stackoverflow bugged out again and I can't post for -9 days cause I posted 6 recent(not even recent) questions.
5) Create a trigger (UpdateTrigger) that outputs a message saying "Student record is going to be updated” Before the Update Takes place on Student Table,
I did
CREATE OR REPLACE TRIGGER UpdateTriggers
BEFORE UPDATE ON StudentsInfo
BEGIN
DBMS_OUTPUT.PUT_LINE('Student record is going to be updated');
Update StudentsInfo Set StudentsUpdated = StudentsUpdated + 1;
End;
and how would I execute it?
begin
UpdateTriggers;
end;
1. Error in PrintProc
The error in following code:
begin
PrintProc;
end;
is caused by the invalid character ’ in DBMS_OUTPUT.PUT_LINE in PrintProc. Replace ’ with ', this should resolve that error.
DBMS_OUTPUT.PUT_LINE('This is the Final Test');
2. Error in UpdateProc
The error in UpdateProc is caused by missing semi-colon in update statement. Add semicolon like the following:
Update Student
set s_state = 'New York'
where s_state = 'WI';
3. Error in PrintStudentsProc
Regarding the error in PrintStudentsProc, you can't do plain select statement inside plsql block. You need to use cursor. Also, you are missing semi-colon in the following query:
Select S.S_ID, F.F_ID
FROM Faculty F INNER JOIN STUDENT S ON F.F_ID = S.F_ID
WHERE F.F_ID = 1;
Cursor for loop example:
CREATE OR REPLACE PROCEDURE PrintStudentsProc AS
BEGIN
FOR stud_rec IN (
Select S.S_ID SID, F.F_ID FID
FROM Faculty F INNER JOIN STUDENT S ON F.F_ID = S.F_ID
WHERE F.F_ID = 1)
LOOP
DBMS_OUTPUT.PUT_LINE(stud_rec.SID||', '||stud_rec.FID);
END LOOP;
END;
/
Have a look at other types of cursors here
4. Error in Trigger
For trigger, after creating the trigger you need to execute the statement which invokes the trigger. In your case it is before update, so you need to perform a update query on the table.
CREATE OR REPLACE TRIGGER update_trigger BEFORE
update ON StudentsInfo FOR EACH ROW
DECLARE
stud_updated int;
BEGIN
DBMS_OUTPUT.PUT_LINE('Student record is going to be updated');
select StudentsUpdated into stud_updated from StudentsInfo where s_id=:new.s_sid;
--increase the value
stud_updated := stud_updated+1;
Update StudentsInfo Set StudentsUpdated = :stud_updated;
DBMS_OUTPUT.PUT_LINE('Student updated count:'||stud_updated);
END;
/
The above trigger should be able to execute, whenever you perform an update on the StudentsInfo table.
Also, check this sqlfiddle
I am trying to list procedures and triggers in the database, but I have to use procedure or function to do so.
This query returns exactly what I need, but I need to get the same results using PL/SQL.
select *
from all_source
where type = 'PROCEDURE'
this query returns exactly what I need, but I have to get the same results using PL/SQL.
Thank you
Try this
declare record all_source%ROWTYPE
begin
select * into record from all_source where type = ?
end;
Try with the below procedure,
CREATE OR REPLACE
PROCEDURE get_proc_list(
i_type IN VARCHAR2,
o_result OUT sys_refcursor)
IS
l_type VARCHAR2(10) := UPPER(i_type);
BEGIN
OPEN o_result FOR
SELECT * FROM all_source
WHERE TYPE = l_type;
END;
To Execute the procedure,
var o_result refcursor;
EXECUTE get_proc_list('procedure',:o_result);
print o_result;