I have a problem to create function my database in oracle - oracle

I have a problem with functions in oracle.
I am trying to add a new row to an existing table but I don't know if I'm going the right direction all the time I have an error.
The function worked in Postgresql and now wants to transform it into Oracle.
Function:
CREATE OR REPLACE FUNCTION add_human(
first_name VARCHAR(15),
last_name VARCHAR (15),
birthday DATE,
pesel BIGINT,
employee_function(VARCHAR(15))
RETURNS void AS
$$ BEGIN
INSERT INTO WORKERS(first_name, last_name, birthday, pesel, employee_function)
VALUES ($1, $2, $3, $4, $5); END; $$ LANGUAGE plpgsql;
Select:
select add_human(‘John’,’Wick’,’1971-01-27’,’71012745639’,’Actor’);

In Oracle, you'd use a procedure to insert rows into a table, not a function (they are to be used to return certain value).
That would be something like this:
SQL> CREATE OR REPLACE PROCEDURE add_human
2 (
3 p_first_name in VARCHAR2,
4 p_last_name in VARCHAR2,
5 p_birthday in DATE,
6 p_pesel in NUMBER,
7 p_employee_function in VARCHAR2
8 )
9 AS
10 BEGIN
11 INSERT INTO WORKERS
12 (first_name, last_name, birthday, pesel, employee_function)
13 VALUES (p_first_name, p_last_name, p_birthday, p_pesel, p_employee_function);
14 END add_human;
15 /
Procedure created.
SQL> BEGIN
2 add_human('John', 'Wick', date '1971-01-27', 71012745639, 'Actor');
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> SELECT * FROM workers;
FIRST_NAME LAST_NAME BIRTHDAY PESEL EMPLOYEE_F
---------- ---------- ---------- -------------- ----------
John Wick 1971-01-27 71012745639 Actor
SQL>

Related

Stored procedure with select count(*) and use count in IF statement

I am creating a stored procedure in Oracle database that's resulting in error "ORA-01858: a non-numeric character was found where a numeric was expected".
My procedure is as below:
create or replace procedure testProc(
id IN VARCHAR2,
user IN VARCHAR2,
sender IN VARCHAR2
)
as
vCount number;
begin
select count(*) into vCount from table1 where id='12345'
if vCount=0
insert into table1 (id, user, sender, status) values (id, user, partner, status);
else
update table1 set status='ERR' where id='12345'
end if;
end procedure;
Error: ORA-01858: a non-numeric character was found where a numeric was expected
I tried replacing vCount as int that did not help. Also tried declaring vCount below sender IN VARCHAR2.
Can someone please tell what is correct way to use the above procedure.
Use a MERGE statement then you can do it in a single statement (rather than SELECT followed by either INSERT or UPDATE):
CREATE PROCEDURE testProc(
i_id IN table1.id%TYPE,
i_user IN table1."USER"%TYPE,
i_sender IN table1.sender%TYPE,
i_status IN table1.status%TYPE
)
AS
BEGIN
MERGE INTO table1 dst
USING (
SELECT '12345' AS id
FROM DUAL
) src
ON (src.id = dst.id)
WHEN MATCHED THEN
UPDATE SET status = 'Err'
WHEN NOT MATCHED THEN
INSERT (id, "USER", sender, status)
VALUES (i_id, i_user, i_sender, i_status);
END testProc;
/
db<>fiddle here
This code can't possibly return error you specified because
procedure is invalid (mising statement terminators; column name can't be USER because it is a keyword, reserved for currently logged user)
that error code is related to date issues, while - in your code - there's nothing that looks like a date
Therefore, it is impossible to help you with error you stated. Otherwise, consider NOT naming procedure's parameters the same as column names because that leads to various problems.
Something like this would work, but it is not related to error you got.
Sample table:
SQL> CREATE TABLE table1
2 (
3 id VARCHAR2 (5),
4 c_user VARCHAR2 (20),
5 partner VARCHAR2 (10),
6 sender VARCHAR2 (10),
7 status VARCHAR2 (5)
8 );
Table created.
SQL>
Procedure:
SQL> CREATE OR REPLACE PROCEDURE testProc (p_id IN VARCHAR2,
2 p_user IN VARCHAR2,
3 p_sender IN VARCHAR2)
4 AS
5 vCount NUMBER;
6 BEGIN
7 SELECT COUNT (*)
8 INTO vCount
9 FROM table1
10 WHERE id = p_id;
11
12 IF vCount = 0
13 THEN
14 INSERT INTO table1 (id,
15 c_user,
16 sender,
17 status)
18 VALUES (p_id,
19 p_user,
20 NULL,
21 'NEW');
22 ELSE
23 UPDATE table1
24 SET status = 'ERR'
25 WHERE id = p_id;
26 END IF;
27 END testproc;
28 /
Procedure created.
Testing:
SQL> EXEC testproc('12345', 'Little', 'Foot');
PL/SQL procedure successfully completed.
SQL> SELECT * FROM table1;
ID C_USER PARTNER SENDER STATU
----- -------------------- ---------- ---------- -----
12345 Little NEW
SQL> EXEC testproc('12345', 'Little', 'Foot');
PL/SQL procedure successfully completed.
SQL> SELECT * FROM table1;
ID C_USER PARTNER SENDER STATU
----- -------------------- ---------- ---------- -----
12345 Little ERR
SQL>

Tips on how to calculate the age on PL/SQL

I created an SQL script:
{CREATE TABLE ator (
id NUMBER(3) NOT NULL,
nome_artistico VARCHAR2(25) NOT NULL,
nss NUMBER(11),
sexo CHAR(1),
nacionalidade VARCHAR2(15),
email VARCHAR2(30),
telefone_fixo VARCHAR2(12),
telefone_movel VARCHAR2(12),
dt_nascimento DATE,
CONSTRAINT ator_pk PRIMARY KEY ( id )
);}
My question is: Does anyone has a tip on how to calculate and print the age of x actor? I'm great at SQL but not so good on PL/SQL so if anyone could give a tip I would appreciate it a lot.
You can use months_between as follows:
Select t.*, trunc(months_between(sysdate, dt_nascimento) / 12) as age
From ator t
As you're interested in PL/SQL solution, I'd suggest you to use a function: pass actor's ID to it and return actor's age. A simple example:
SQL> create or replace function f_age (par_id in ator.id%type)
2 return number
3 is
4 l_age number;
5 begin
6 select round(months_between(sysdate, a.dt_nascimento) / 12)
7 into l_age
8 from ator a
9 where a.id = par_id;
10
11 return l_age;
12 end;
13 /
Function created.
SQL> select f_age(5) from dual;
F_AGE(5)
----------
54
SQL>

In Oracle, how do i create stored procedure to insert value in 2 tables

I am trying to insert below details in two table. but it shows error. where i am wrong?
create or replace PROCEDURE ADD_customer_order(
customer_id in varchar, Shipping_id_arg in number,
order_date_arg in date, Total_price_arg in decimal,
inventory_id_arg in number, order_quantity_arg in number)
AS
BEGIN
INSERT INTO customer_order (customer_id,Shipping_id,Order_date,total_price) VALUES(customer_id_arg,Shipping_id_arg,order_date_arg, total_price_arg);
insert into order_details (inventory_id,order_quantity) values(scope_identity(),inventory_id_arg,order_quantity_arg);
END;
It helps if you format it nicely.
create or replace procedure add_customer_order(
customer_id in varchar2, shipping_id_arg in number,
order_date_arg in date , total_price_arg in decimal,
inventory_id_arg in number , order_quantity_arg in number)
as
begin
insert into customer_order
(customer_id , shipping_id , order_date , total_price)
values
(customer_id_arg, shipping_id_arg, order_date_arg, total_price_arg);
insert into order_details
( inventory_id , order_quantity)
values
(scope_identity(), inventory_id_arg, order_quantity_arg);
end;
Doing so, you easily note that the second INSERT is invalid, as you're inserting 3 values into 2 columns:
insert into order_details
( inventory_id , order_quantity)
values
(scope_identity(), inventory_id_arg, order_quantity_arg);
Either remove scope_identity() (what is it?), or include additional column into the column list you're inserting into.
After reading your comment, it seems that returning clause might help. See the following example (somewhat simpler than yours; didn't feel like typing that much). Trigger is used to auto-increment ORDER_ID column. in CUSTOMER_ORDER table (I'm on 11g XE; don't have identity columns here).
SQL> create table customer_order (order_id number, customer_id number);
Table created.
SQL> create table order_details (order_id number, inventory_id number);
Table created.
SQL> create sequence seqo;
Sequence created.
SQL> create or replace trigger trg_co
2 before insert on customer_order
3 for each row
4 begin
5 :new.order_id := seqo.nextval;
6 end;
7 /
Trigger created.
Procedure: note local variable declared in line #4 and returning clause in line #7:
SQL> create or replace procedure p_test
2 (par_customer_id in number, par_inventory_id in number)
3 is
4 l_order_id customer_order.order_id%type;
5 begin
6 insert into customer_order (customer_id) values (par_customer_id)
7 returning order_id into l_order_id;
8
9 insert into order_details (order_id, inventory_id)
10 values (l_order_id, par_inventory_id);
11 end;
12 /
Procedure created.
Testing:
SQL> exec p_test(100, 200);
PL/SQL procedure successfully completed.
SQL> exec p_test (235, 2230);
PL/SQL procedure successfully completed.
SQL> select * From customer_order;
ORDER_ID CUSTOMER_ID
---------- -----------
1 100
2 235
SQL> select * From order_details;
ORDER_ID INVENTORY_ID
---------- ------------
1 200
2 2230
SQL>
The same ORDER_ID value is used in both tables.

Oracle SQL - ORA-04079: invalid trigger insert

I am trying to create a trigger that runs when I insert in table 'cuenta' and make an insert in table 'cuenta_log', one of the values of this insert is gotten by accept input.
create or replace trigger trigger_new_account
AFTER INSERT ON cuenta FOR EACH ROW
accept vstring prompt "Please enter your name: ";
declare v_line varchar2(50);
begin
v_line:= 'Hello '||'&vstring';
insert into cuentas_log (fecha,cuenta,cliente)
values (now(),:new.idcuenta,v_line);
end;
cuenta_log structure is like that:
cuenta_log
("FECHA" DATE DEFAULT (sysdate),
"CUENTA" NUMBER(38,0),
"CLIENTE" VARCHAR2(50 BYTE)
)
Trigger fires on certain event; yours, after insert into table named cuenta. It doesn't work interactively with end users. You can't expect it to prompt anyone to enter anything. Besides, accept is a SQL*Plus command, it won't work in PL/SQL.
So, here's what you might have done: sample tables first:
SQL> create table cuenta (fecha date, cuenta number);
Table created.
SQL> create table cuenta_log (fecha date, cuenta number, cliente varchar2(30));
Table created.
Trigger:
SQL> create or replace trigger trigger_new_account
2 after insert on cuenta
3 for each row
4 begin
5 insert into cuenta_log(fecha, cuenta, cliente)
6 values
7 (sysdate, :new.cuenta, 'Hello ' || user);
8 end;
9 /
Trigger created.
Testing:
SQL> insert into cuenta (fecha, cuenta) values (sysdate, 100);
1 row created.
SQL> select * From cuenta;
FECHA CUENTA
------------------- ----------
11.05.2020 12:31:17 100
SQL> select * From cuenta_log;
FECHA CUENTA CLIENTE
------------------- ---------- ------------------------------
11.05.2020 12:31:17 100 Hello SCOTT
SQL>

pl/sql stored procedure to select from a table where date is equal to stored procedure parameter

I am new to PL/SQL and oracle, I am using SQL developer 19 against an Oracle 12C database.
All I am trying to do, as I am used to do in T-SQL, is to select some data from a table where a date field value is between two stored procedure ate parameters; below the stored procedure I am using that give to me an error saying that I have to "SELECT INTO" ??
create or replace PROCEDURE GET_DMR_HALO_VALUES ( START_DATE IN DATE , END_DATE IN DATE )
AS
BEGIN
SELECT
HALO_RECORD_ID ,
ASSET_ID ,
ASSET_NAME ,
NUMERIC_VALUE ,
IS_ENABLED ,
ADDED_BY ,
VALUE_DATE ,
NOTES ,
DATE_ADDED
FROM halo_inputs
WHERE trunc(value_date) BETWEEN START_DATE and END_DATE;
END GET_DMR_HALO_VALUES;
then I also have another problem... assuming that the above works I am trying to view the returned table data by calling the stored procedure in SQL developer as follow
DEFINE START_DATE date := TO_DATE('2019-02-12','YYYY-DD-MM');
DEFINE END_DATE date := TO_DATE('2019-02-12','YYYY-DD-MM');
exec GET_DMR_HALO_VALUES(:START_DATE, :END_DATE );
Am I right by calling the SP like above?
UPDATE
after looking at this stack-over article
I changed the stored procedure as follow
create or replace PROCEDURE GET_DMR_HALO_VALUES ( START_DATE IN DATE , END_DATE IN DATE )
AS
c1 sys_refcursor;
BEGIN
open c1 for
SELECT
HALO_RECORD_ID ,
ASSET_ID ,
ASSET_NAME ,
NUMERIC_VALUE ,
IS_ENABLED ,
ADDED_BY ,
VALUE_DATE ,
NOTES ,
DATE_ADDED
FROM halo_inputs
WHERE trunc(value_date) BETWEEN START_DATE and END_DATE;
dbms_sql.return_result(c1);
END;
but are cursors the only way in Oracle to get table data ?
UPDATE 2
I also changed the exec query as follow
DECLARE
START_DATE date := TO_DATE('12-02-20','DD-MM-YY');
END_DATE date := TO_DATE('12-02-20','DD-MM-YY');
BEGIN
GET_DMR_HALO_VALUES(START_DATE,END_DATE );
END;
and it works but how I get SQL developer to display data in a grid view rather than in plain text ?
The simplest option to make this query return data in data grid is to ... well, run it outside of the stored procedure. Procedures are nice, but not that nice for doing what you want.
When returning something, a function might be a better choice. For example:
Create it first:
SQL> create or replace FUNCTION f_test (par_deptno in number)
2 return sys_refcursor
3 is
4 l_rc sys_refcursor;
5 begin
6 open l_rc for
7 select empno, ename, job, sal
8 from emp
9 where deptno = par_deptno;
10 return l_rc;
11 end;
12 /
Function created.
Then call it:
SQL> select f_test(10) from dual;
F_TEST(10)
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7782 CLARK MANAGER 2450
7839 KING PRESIDENT 5000
7934 MILLER CLERK 1300
SQL>
In SQL Developer, you'd run the last statement (select f_test(10) from dual;) as a script (F9 keyboard shortcut) and it'll then display the result nicely (as my example shows above, although it is SQL Plus command line tool output). Though, it still won't be in a data grid.

Resources