Oracle error: expression '' cannot be used as an assignment target - oracle

When I try to execute the stored procedure, all the parameters that I pass to it, appears "expression '(parameter)' cannot be used as an assignment target", I don't know what the problem is.
This is the stored procedure:
create or replace PROCEDURE INSTERT_UPDATE_EMPLEADO
(
CEDULA IN OUT INTEGER,
ID_CARGO IN OUT INTEGER,
ID_EMP IN OUT INTEGER,
NOMBRE IN OUT VARCHAR,
APELLIDO IN OUT VARCHAR,
FECHA_NAC IN OUT INTEGER,
FECHA_CON IN OUT INTEGER,
SALARIO IN OUT INTEGER
) AS
BEGIN
IF ID_EMP = 0 THEN
INSERT INTO EMPLEADO("CEDULA_EMPLEADO", "ID_CARGO", "EMPLEADO_ID", "NOMBRE", "APELLIDO", "FECHA_NAC", "FECHA_CONTRATO", "SALARIO")
VALUES (CEDULA, ID_CARGO, ID_EMP, NOMBRE, APELLIDO, FECHA_NAC, FECHA_CON, SALARIO);
ELSE
UPDATE EMPLEADO SET NOMBRE = NOMBRE, APELLIDO = APELLIDO, FECHA_NAC = FECHA_NAC, FECHA_CONTRATO = FECHA_CON, SALARIO = SALARIO,
CEDULA_EMPLEADO = CEDULA, ID_CARGO = ID_CARGO WHERE EMPLEADO_ID = ID_EMP;
END IF;
COMMIT;
END INSTERT_UPDATE_EMPLEADO;

Since you are going to insert or update the table, you need to create the table first.
If you already have the table, please ignore this step:
create table EMPLEADO
(
CEDULA NUMBER(5),
ID_CARGO NUMBER(5),
ID_EMP NUMBER(5),
NOMBRE VARCHAR2(20),
APELLIDO VARCHAR2(20),
FECHA_NAC NUMBER(5),
FECHA_CON NUMBER(5),
SALARIO NUMBER(5)
)
Then create the stored procedure:
CREATE OR REPLACE PROCEDURE INSTERT_UPDATE_EMPLEADO(
P_CEDULA IN EMPLEADO.CEDULA%TYPE,
P_ID_CARGO IN EMPLEADO.ID_CARGO%TYPE,
P_ID_EMP IN EMPLEADO.ID_EMP%TYPE,
P_NOMBRE IN EMPLEADO.NOMBRE%TYPE,
P_APELLIDO IN EMPLEADO.APELLIDO%TYPE,
P_FECHA_NAC IN EMPLEADO.APELLIDO%TYPE,
P_FECHA_CON IN EMPLEADO.FECHA_CON%TYPE,
P_SALARIO IN EMPLEADO.SALARIO%TYPE)
IS
BEGIN
IF P_ID_EMP = 0 THEN
INSERT INTO EMPLEADO("CEDULA_EMPLEADO", "ID_CARGO", "EMPLEADO_ID", "NOMBRE", "APELLIDO", "FECHA_NAC", "FECHA_CONTRATO", "SALARIO")
VALUES (P_CEDULA, P_ID_CARGO, P_ID_EMP, P_NOMBRE, P_APELLIDO, P_FECHA_NAC, P_FECHA_CON, P_SALARIO);
ELSE
UPDATE EMPLEADO
SET NOMBRE = P_NOMBRE,
APELLIDO = P_APELLIDO,
FECHA_NAC = P_FECHA_NAC,
FECHA_CONTRATO = P_FECHA_CON,
SALARIO = P_SALARIO,
CEDULA_EMPLEADO = P_CEDULA,
ID_CARGO = P_ID_CARGO
WHERE EMPLEADO_ID = P_ID_EMP;
END IF;
COMMIT;
END;

The problem not in the procedure itself, but in its interface. out and in out parameters write their values back as output. For example:
create table demo (id integer);
Procedure (creates without errors):
create or replace procedure insert_demo
( id in out demo.id%type )
as
begin
insert into demo (id) values (id);
end insert_demo;
Call fails, because the literal value 1 can't be updated with the out value returned by the procedure:
SQL> exec insert_demo(1)
BEGIN insert_demo(1); END;
*
ERROR at line 1:
ORA-06550: line 1, column 19:
PLS-00363: expression '1' cannot be used as an assignment target
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
If you are going to use out or in out parameters, you have to pass variables (SQL*Plus example below, though you could just call it from another procedure passing a normal PL/SQL variable):
SQL> var id number
SQL> exec :id := 1
PL/SQL procedure successfully completed.
ID
----------
1
SQL> exec insert_demo(:id)
PL/SQL procedure successfully completed.
ID
----------
1
The solution is therefore either to pass variables, or to change the parameter mode to in:
create or replace procedure insert_demo
( id in demo.id%type )
as
begin
insert into demo (id) values (id);
end insert_demo;
Test:
SQL> exec insert_demo(1)
PL/SQL procedure successfully completed.
It is generally good practice to avoid using column names for PL/SQL parameters and variables, for example by prefixing parameters with p_ and local variables with l_. Or if you must, you can use dot notation and the procedure name, e.g. insert_demo.id or instert_update_empleado.salario would specify the procedure parameter and not the table column. However, that is not the cause of the issue here.
(Also, your caps lock is on.)

Related

RTTI in Oracle Triggers

I have this dummy types :
create or replace type Service_TY as object(
code INTEGER,
visit_analysis char(1)
)FINAL;
/
create or replace type Employee_TY as object(
dummy varchar(30)
)NOT FINAL;
/
create or replace type Doctor_TY UNDER Employee_TY(
ID INTEGER
)FINAL;
/
create or replace type Assistant_TY UNDER Employee_TY(
ID INTEGER
)FINAL;
/
create or replace type Habilitation_TY as object(
employee ref Employee_TY,
service ref Service_TY
)FINAL;
/
And these dummy tables:
CREATE TABLE Service of Service_TY(
code primary key,
visit_analysis not null check (visit_analysis in ('v', 'a'))
);
/
CREATE TABLE Doctor of Doctor_TY(
ID primary key
);
/
CREATE TABLE Assistant of Assistant_TY(
ID primary key
);
/
CREATE TABLE Habilitation of Habilitation_TY;
/
I want to create a trigger that, when a new tuple is inserted in Habilitation, should check that, if the employee is an assistant (and not a doctor), the visit_analysis attribute is equal to 'a' to know if it is a legal tuple.
I don't know how to check the type of the Employee (if it is a doctor or an assistant).
I would do something like that:
create or replace
TRIGGER CHECK_HABILITATION
BEFORE INSERT ON HABILITATION
FOR EACH ROW
DECLARE
BEGIN
IF (:NEW.EMPLOYEE is of ASSISTANT_TY)
THEN
IF :NEW.SERVICE.visit_analysis = 'v'
THEN
raise_application_error(-10000, 'invalid tuple');
END IF;
END;
But it's not working.
How should I check that type?
The error I get is:
Error(14,4): PLS-00103: Encountered the symbol ";" when expecting one of the following: if
Try to put it into a variable, the following one should work.
create or replace
TRIGGER CHECK_HABILITATION
BEFORE INSERT ON HABILITATION
FOR EACH ROW
DECLARE
emp employee_TY;
ser service_TY;
BEGIN
select deref(:new.employee) into emp from dual;
if (emp is of (assistant_ty)) then
select deref(:new.service) into ser from dual;
if ser.visit_analysis = 'v' then
raise_application_error('-20001', 'invalid tuple');
end if;
end if;
END;
/
According to the documentation for the IS OF condition, you need to wrap the type in parentheses, like:
IF (:NEW.EMPLOYEE is of (ASSISTANT_TY) )
per https://docs.oracle.com/cd/B28359_01/server.111/b28286/conditions014.htm#SQLRF52157.
I'm not really familiar with using object types so there may be some other issue that I'm not seeing.

Create procedure with if in oracle sql

I need to create a procedure that search an email in a table, and if it doesn´t exists the procedure creates a new record with this email.
Something like this:
CREATE PROCEDURE check_email (in #email varchar2(99)) AS
BEGIN
IF SELECT email FROM user u WHERE u.email:=email
dbms_output.put_line('This email exists');
ELSE
BEGIN
INSERT INTO user (id, name, surname, city, address, age, email) VALUES (id_user.nextval,'David','Alcatraz','Sevilla', 'Avd miguel de unamuno', 23, email || '#gmail.com')
END
Take this in consideration:
A variable to store the counter of email from the table.
You must close each statement with semicolon.
An input variable is defined with its type without length.
It would look like
CREATE PROCEDURE check_email (p_email in varchar2 ) AS
v_counter pls_integer;
BEGIN
SELECT count(*) into v_counter FROM user WHERE upper(email) = upper(p_email);
if v_counter = 1
then
dbms_output.put_line('This email exists');
ELSE
INSERT INTO user (id, name, surname, city, address, age, email) VALUES
(id_user.nextval,'David','Alcatraz','Sevilla', 'Avd miguel de unamuno', 23, p_email ||
'#gmail.com');
commit;
END IF;
exception when others then raise;
END;
Why bother? Let the database handle that.
Here's how: as e-mail addresses have to be unique, create a unique key constraint on that column:
SQL> create table t_user
2 (id number constraint pk_user primary key,
3 name varchar2(20) not null,
4 e_mail varchar2(30) not null,
5 --
6 constraint uk_user_mail unique (e_mail)
7 );
Table created.
Sequence will be used for the ID column values.
SQL> create sequence tseq;
Sequence created.
Procedure: if there's unique key violation, simply don't do anything. Other errors, if any, will be automatically raised by Oracle. You can handle them, if you want.
SQL> create or replace procedure p_user
2 (par_name in t_user.name%type,
3 par_email in t_user.e_mail%type)
4 is
5 begin
6 insert into t_user (id, name, e_mail)
7 values (tseq.nextval, par_name, par_email);
8 exception
9 when dup_val_on_index then null;
10 end;
11 /
Procedure created.
Testing:
SQL> exec p_user('Little', 'lf#mail.com');
PL/SQL procedure successfully completed.
SQL> exec p_user('Foot' , 'lf#mail.com');
PL/SQL procedure successfully completed.
SQL> exec p_user('Victor', 'victor#mail.com');
PL/SQL procedure successfully completed.
SQL> select * From t_user;
ID NAME E_MAIL
---------- -------------------- ------------------------------
1 Little lf#mail.com
3 Victor victor#mail.com
SQL>
As you can see, Foot never entered the table as its e-mail address already exists in the table.

How can I deal with PL-SQL package error PLS-00103: Encountered the symbol "(" when expecting one of the following: := )

There is a similar answer for the problem I have, but it seems that this answer is for procedure issue.
I supposed to make a pl sql package which has 3 procedures inside. It's gonna be like that:
CREATE OR REPLACE PACKAGE Count_num AS
PROCEDURE count_emps(dno IN number);
PROCEDURE count_deps(empssn IN char(9));
PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15));
END;
/
show errors
CREATE OR REPLACE PACKAGE BODY Count_num AS
PROCEDURE count_emps(dno IN number)
AS
cnt number;
BEGIN
SELECT COUNT(*) INTO cnt
WHERE Department.dnumber = Employee.dno
AND Department.dnumber = dno;
dbms_output.put_line('Number of Employee is ' || cnt);
END;
PROCEDURE count_deps(empssn IN char(9))
AS
cnt2 number;
BEGIN
SELECT COUNT(*) INTO cnt2
WHERE Dependent.essn = Employee.ssn
AND Department.essn = empssn;
dbms_output.put_line('Number of dependent is ' || cnt2);
END;
PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15))
AS
BEGIN
DELETE *
FROM Dependent
WHERE Dependent.essn = Employee.ssn
AND Dependent.essn = empssn
AND Dependent.dependent_name = dname;
SELECT *
FROM Dependent
WHERE Dependent.essn = Employee.ssn
AND Dependent.essn = empssn
AND Dependent.dependent_name = dname;
END;
END;
/
show errors
EXEC Count_num.count_emps(5);
EXEC Count_num.count_deps('333445555');
EXEC Count_num.delete_deps('333445555', 'Alice')
show errors
count_emps counts the number of employees for a department,
count_deps counts the number of dependents for a valid employee,
delete_deps deletes a specific depdendent. It's creation query is like below:
drop table Employee cascade constraints;
commit;
create table Employee
(
fname varchar2(15),
minit varchar2(1), -- can be char
lname varchar2(15),
ssn char(9),
bdate date,
address varchar2(50),
sex varchar2(1) CHECK(Sex = 'M' or Sex = 'F'),
salary number, -- need to put check on salary
superssn char(9),
dno number DEFAULT 0,
constraint EMPPK
primary key(ssn),
constraint EMPSUPERVRFK
foreign key(superssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Department cascade constraints;
commit;
create table Department
(
dname varchar2(15) NOT NULL,
dnumber number,
mgr_ssn char(9) DEFAULT '000000000',
mgr_start_date date,
constraint DEPTPK
primary key(dnumber),
constraint DEPTMGRFK
foreign key(mgr_ssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Dependent cascade constraints;
commit;
create table Dependent
(
Essn char(9),
Dependent_name varchar2(15),
Sex varchar2(15),
Bdate date,
Relationship varchar2(15),
constraint DEPENDPK
primary key (Essn, Dependent_name),
constraint DEPENDFK
foreign key(Essn) references Employee(Ssn)
);
When I execute package queries, it gives me an error like below:
SQL> CREATE OR REPLACE PACKAGE Count_num AS
2 PROCEDURE count_emps(dno IN number);
3 PROCEDURE count_deps(empssn IN char(9));
4 PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15));
5 END;
6 /
Warning: Package created with compilation errors.
Elapsed: 00:00:00.02
SQL> show errors
Errors for PACKAGE COUNT_NUM:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/37 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= ) , default varying character large
The symbol ":=" was substituted for "(" to continue.
4/38 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= ) , default varying character large
The symbol ":=" was substituted for "(" to continue.
4/60 PLS-00103: Encountered the symbol "(" when expecting one of the
LINE/COL ERROR
-------- -----------------------------------------------------------------
following:
:= . ) , # % default character
The symbol ":=" was substituted for "(" to continue.
I can't recognize what this error is, so anyone can explain what this error is, and how can I handle this issue?
Remove the length specified for the data types in the arguments.
Also, better to specify the column data type than hard-coding it.
CREATE OR REPLACE PACKAGE Count_num AS
PROCEDURE count_emps(i_dno IN employee.dno%TYPE);
PROCEDURE count_deps(i_empssn IN employee.ssn%TYPE);
PROCEDURE delete_deps(i_empssn IN employee.ssn%TYPE,
i_dname IN department.dname%TYPE
);
END;
/

Oracle - How to Create Table with Two Columns that grow like 2D array?

I want to create a table for logging purpose in such a way that when I will insert into table I have an Execution order column that increment per RequestID-wise.
CREATE TABLE WSRequestLog
(
RequestId NUMBER,
ExecOrder INTEGER,
MobileNo VARCHAR2(50),
CardNo VARCHAR2(50),
Log_Text VARCHAR2(4000),
DateTime date
PRIMARY KEY (RequestId, ExecOrder)
);
PROCEDURE Generate
.
.
.
IF first_condition = TRUE THEN
INSERT INTO WSRequestLog (RequestId, ExecOrder, MobileNo, CardNo, Log_Text, DateTime)
VALUES (v_req_id, Auto_Incremenet or NextVal, v_mobile_no, v_card_no, 'Performing First Step', SYSDATE);
--Execute Code
IF second_condition = TRUE THEN
INSERT INTO WSRequestLog (RequestId, ExecOrder, MobileNo, CardNo, Log_Text,DateTime)
VALUES (v_req_id, Auto_Incremenet or NextVal, v_mobile_no, v_card_no, 'First Step executed, checking next step', SYSDATE);
--Execute Code
ELSE
INSERT INTO WSRequestLog (RequestId, ExecOrder, MobileNo, CardNo, Log_Text,DateTime)
VALUES (v_req_id, Auto_Incremenet or NextVal, v_mobile_no, v_card_no, 'Second Step not applicable', SYSDATE);
--Execute Code
END IF;
END IF;
END Generate;
My question is how to achieve this type of insertion?
So that if I execute the Stored Procedure, the log table would be like this:
Have a package which is pragma serially reusable which will have one variable set to null.
In other package which contains core logger code, verify if the variable is null then set request id variable value - which is a package variable- You will increment this value in your case. for exec order follow the logic as in below lines
procedure set_log_sequence(p_log_sequence in number) as
begin
if p_log_sequence is null then
gv_log_sequence := gv_log_seq;
gv_log_seq := gv_log_seq+1;
else
gv_log_sequence := p_log_sequence;
end if;
end;

Oracle Run Procedure with one in parameter and multiple out parameter

I just started working with Oracle and I'm using SQL Developer to test before I start adding stuff to my application, but I'm running into issues because Oracle behaves differently than every other database engine I've worked with.
I created a dummy table:
CREATE TABLE "ROOT"."EMPLOYEES"
( "ID" NUMBER NOT NULL ENABLE,
"FIRSTNAME" VARCHAR2(30 BYTE) NOT NULL ENABLE,
"LASTNAME" VARCHAR2(30 BYTE) NOT NULL ENABLE,
"EMAIL" VARCHAR2(40 BYTE) NOT NULL ENABLE,
CONSTRAINT "EMPLOYEES_PK" PRIMARY KEY ("ID")
)
And Then I created a Procedure:
create or replace PROCEDURE get_employee
(
emp_id IN NUMBER,
m_FirstName OUT Varchar2,
m_LastName OUT Varchar2,
m_Email OUT Varchar2
)
AS
BEGIN
SELECT
FirstName
,LastName
,Email
INTO
m_FirstName,
m_LastName,
m_Email
FROM EMPLOYEES
WHERE
ID = emp_id;
END get_employee;
The problem is I get compilation errors when I try to run the procedure:
Declare x VARCHAR2(30);
y VARCHAR2(30);
z VARCHAR2(40);
Begin
exec GET_EMPLOYEE(1, :x, :y, :z);
SYS.DBMS_OUTPUT.PUT_LINE(x);
End;
I get this error:
ORA-06550: line 8, column 4:
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
an identifier a double-quoted
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
PL/SQL procedure successfully completed.
I'm really not sure how to change my call to the procedure to make it work with SQL Developer. Any help would be greatly appreciated.
This is the correct syntax
Declare
x VARCHAR2(30);
y VARCHAR2(30);
z VARCHAR2(40);
Begin
GET_EMPLOYEE(1, x, y, z);
DBMS_OUTPUT.PUT_LINE(x);
End;
Or an another version of stub execution.
var x varchar2(30);
var y varchar2(30);
var z varchar2(40);
exec GET_EMPLOYEE(1, :x, :y, :z);

Resources