insert function with user prompt - oracle

I'm trying to make an Oracle function to be used with Oracle SQL Developer that the user can type cnp from the keyboard and if the cnp size is = 13 then insert it into the table that the user has loaded. if it is not = 13 then a message appears.
I did the job but it shows me errors .. I tried, I documented but I did not find where I'm wrong.
here is my table, for now I just want cnp to add it, after I will introduce the rest of the attributes in the table.:
CREATE TABLE CLIENT (
CODCLIENT NUMBER,
NUMECLIENT VARCHAR2(10),
PRENUMECLIENT VARCHAR2(15),
CNPCLIENT VARCHAR2(13),
SERIECLIENT VARCHAR2(2),
NUMARID VARCHAR2(6),
SEX VARCHAR2(10) CONSTRAINT NN_SEXC NOT NULL CONSTRAINT CK_SEXC CHECK((SEX) IN('MASCULIN','FEMININ')),
ADRESA VARCHAR2(100),
EMAIL VARCHAR2(50),
TELEFON VARCHAR2(13),
CONSTRAINT PK_CODCLIENT PRIMARY KEY (CODCLIENT)
);
And here is the error displayed:
old:DECLARE
CNP varchar2(13);
BEGIN
CNP := '&X' ;
IF CNP.LENGTH = 13 THEN
INSERT INTO CLIENT(CNPCLIENT) VALUES(CNP);
ELSE
DBMS_OUTPUT.PUT_LINE('CNP INCORECT');
END IF;
END;
new:DECLARE
CNP varchar2(13);
BEGIN
CNP := '23241415151' ;
IF CNP.LENGTH = 13 THEN
INSERT INTO CLIENT(CNPCLIENT) VALUES(CNP);
ELSE
DBMS_OUTPUT.PUT_LINE('CNP INCORECT');
END IF;
END;
Error starting at line : 30 in command -
DECLARE
CNP varchar2(13);
BEGIN
CNP := '&X' ;
IF CNP.LENGTH = 13 THEN
INSERT INTO CLIENT(CNPCLIENT) VALUES(CNP);
ELSE
DBMS_OUTPUT.PUT_LINE('CNP INCORECT');
END IF;
END;
Error report -
ORA-06550: line 7, column 12:
PLS-00487: Invalid reference to variable 'CNP'
ORA-06550: line 7, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

Oracle LENGTH function has the following syntax:
LENGTH( string1 )
You can find more about it here: https://www.techonthenet.com/oracle/functions/length.php
In your code, instead of IF CNP.LENGTH = 13 you should'e written the following:
IF LENGTH(CNP) = 13
I hope I helped!

Related

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

PL/SQL trouble at create trigger

CREATE TABLE INVENTORY(
INVENTORY_ID NUMBER(6) PRIMARY KEY,
ITEM_NAME VARCHAR2(255),
QUANTITY NUMBER,
PRICE NUMBER,
ITEM_SIZE VARCHAR(255),
INVENTORY_VALUE NUMBER);
===
CREATE TABLE INVENTORY_AUDIT(
DATE_CHANGED DATE,
USER_NAME VARCHAR2(30),
INV_ID NUMBER(6),
OLD_QUANTITY NUMBER,
NEW_QUANTITY NUMBER,
CONSTRAINT fk_INV_ID
FOREIGN KEY (INV_ID)
REFERENCES INVENTORY (INVENTORY_ID));
===
CREATE OR REPLACE TRIGGER INV_CHG
BEFORE UPDATE OF QUANTITY
ON INVENTORY
FOR EACH ROW
BEGIN
IF :NEW.QUANTITY <> :OLD.QUANTITY THEN
INSERT INTO INVENTORY_AUDIT
VALUES (GETDATE(), v('APP_USER'), :NEW.INVENTORY_ID, :OLD.QUANTITY, :NEW.QUANTITY)
END IF;
END;
===
ORA-24344: success with compilation error
ORA-06512: at "SYS.WWV_DBMS_SQL_APEX_190200", line 592
ORA-06512: at "SYS.DBMS_SYS_SQL", line 1658
ORA-06512: at "SYS.WWV_DBMS_SQL_APEX_190200", line 578
ORA-06512: at "APEX_190200.WWV_FLOW_DYNAMIC_EXEC", line 2057
3. ON INVENTORY
4. FOR EACH ROW
5. BEGIN
6. IF :NEW.QUANTITY <> :OLD.QUANTITY THEN
7. INSERT INTO INVENTORY_AUDIT
===
I tried to create trigger that triggered by inventory table's quantity change.
But it throws an error and syntax looks fine for me.
I tried without IF whole statement but still had same problem.
That means my create trigger statement has problem right?
But I cannot find it.
Two things:
missing semi-colon at the end of the INSERT statement
use sysdate instead of getdate
Here's how:
SQL> CREATE OR REPLACE TRIGGER INV_CHG
2 BEFORE UPDATE OF QUANTITY
3 ON INVENTORY
4 FOR EACH ROW
5 BEGIN
6 IF :NEW.QUANTITY <> :OLD.QUANTITY THEN
7 INSERT INTO INVENTORY_AUDIT
8 VALUES (sysdate, --> sysdate instead of getdate()
9 v('APP_USER'),
10 :NEW.INVENTORY_ID,
11 :OLD.QUANTITY,
12 :NEW.QUANTITY
13 ); --> missing semi-colon here
14 END IF;
15 END;
16 /
Trigger created.
SQL>

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

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.)

Invalid reference to variable PL/SQL

I'm having trouble in getting started with PL/SQL
Here is my code:
SET SERVEROUTPUT ON;
DECLARE
v_cname customers.customer_name%type := '&customer_name';
v_cardno customers.card_number%type := '&card_number';
v_lastcid customers.customer_id%type;
BEGIN
SELECT customer_id INTO v_lastcid from customers
where customer_id = (select max(customer_id) from customers);
dbms_output.put_line(v_lastcid);
INSERT INTO customers(customer_id, customer_name, card_number)
VALUES(v_lastcid.NEXTVAL, v_cname, v_cardno);
COMMIT;
END;
This returns an error:
ORA-06550: line 12, column 20:
PLS-00487: Invalid reference to variable 'V_LASTCID'
ORA-06550: line 12, column 20:
PL/SQL: ORA-02289: sequence does not exist
ORA-06550: line 11, column 13:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
Any help would me much appreciated!
You probably meant to say MAX + 1 (see lines 7 and 12), i.e.
SQL> create table customers
2 (customer_id number,
3 customer_name varchar2(20),
4 card_number varchar2(20));
Table created.
SQL> DECLARE
2 v_cname customers.customer_name%type := '&customer_name';
3 v_cardno customers.card_number%type := '&card_number';
4 v_lastcid customers.customer_id%type;
5
6 BEGIN
7 SELECT nvl(max(customer_id), 0) INTO v_lastcid from customers
8 where customer_id = (select max(customer_id) from customers);
9 dbms_output.put_line(v_lastcid);
10
11 INSERT INTO customers(customer_id, customer_name, card_number)
12 VALUES(v_lastcid + 1, v_cname, v_cardno);
13 COMMIT;
14 END;
15 /
Enter value for customer_name: Little
Enter value for card_number: Foot
0
PL/SQL procedure successfully completed.
SQL> select * from customers;
CUSTOMER_ID CUSTOMER_NAME CARD_NUMBER
----------- -------------------- --------------------
1 Little Foot
SQL>
Although it works, it is doomed to fail in a multi-user environment if two (or more) users fetch the same MAX value; insert would fail with a DUP-VAL-ON-INDEX error (if the ID is supposed to be unique).
Therefore, use a sequence (which is what NEXTVAL in your code suggests):
SQL> create sequence seq_cust;
Sequence created.
SQL> DECLARE
2 v_cname customers.customer_name%type := '&customer_name';
3 v_cardno customers.card_number%type := '&card_number';
4 v_lastcid customers.customer_id%type;
5 BEGIN
6 INSERT INTO customers(customer_id, customer_name, card_number)
7 VALUES(seq_cust.nextval, v_cname, v_cardno);
8 COMMIT;
9 END;
10 /
Enter value for customer_name: Big
Enter value for card_number: Foot
PL/SQL procedure successfully completed.
nextval is used to get the next value from a sequence. It's usually used to create a pseudo primary key. You can think of it like a special function that can only be called on sequences.
v_lastcid is a variable that has the same type as the customer_id column in the customers table. So if you had a table like this...
CREATE TABLE CUSTOMERS ( CUSTOMER_ID INTEGER );
...then v_lastcid is an integer;
If you're trying to make a dummy customer with the next highest number maybe you mean something like...
INSERT INTO customers(customer_id, customer_name, card_number)
VALUES(v_lastcid + 1, v_cname, v_cardno);
Hope this helps.

Exception after calling a procedure of a package from another schema

I have two schemas SCHEMA_1 and SCHEMA_2.
In SCHEMA_1, I have 2 tables, LOCATIONS and COUNCILS, with the following structure:
CREATE TABLE SCHEMA_1.COUNCILS
( ID NUMBER(*,0),
DCOUNCIL VARCHAR2(200 BYTE),
CONSTRAINT COUNCILS_PK PRIMARY KEY ("ID")
);
CREATE TABLE SCHEMA_1.LOCATIONS
( ID NUMBER(*,0),
DLOCATION VARCHAR2(200 BYTE),
COUNCIL_ID NUMBER(*,0),
CONSTRAINT LOCATIONS_PK PRIMARY KEY ("ID"),
CONSTRAINT LOCATIONS_R01 FOREIGN KEY ("COUNCIL_ID")
REFERENCES SCHEMA_1.COUNCILS ("ID") ENABLE
);
I also have, in SCHEMA_1, compiled one package, which includes a function to select the denomination of all locations inside a council:
CREATE OR REPLACE PACKAGE SCHEMA_1.PAQ_LOCATIONS
IS
TYPE t_TABLE_LOCATIONS IS TABLE OF LOCATIONS%ROWTYPE
INDEX BY BINARY_INTEGER;
FUNCTION OBTAIN_ALL
(
pe_council_id IN COUNCILS.ID%TYPE
)
RETURN t_TABLE_LOCATIONS;
END PAQ_LOCATIONS;
CREATE OR REPLACE PACKAGE BODY SCHEMA_1.PAQ_LOCATIONS
IS
FUNCTION OBTAIN_ALL
(
pe_council_id IN COUNCILS.ID%TYPE
)
RETURN t_TABLE_LOCATIONS
IS
CURSOR cur_locations
IS
SELECT *
FROM LOCATIONS
WHERE COUNCIL_ID = pe_council_id;
v_tlocations t_TABLE_LOCATIONS;
v_counter BINARY_INTEGER;
BEGIN
v_counter := 0;
FOR reg_location IN cur_locations
LOOP
v_contador := v_counter + 1;
v_tlocations ( v_counter ) := reg_location;
END LOOP;
RETURN v_tlocations;
END OBTAIN_ALL;
END PAQ_LOCATIONS;
Then, I have granted execution privileges on "PAQ_LOCATIONS" to "SCHEMA_2".
PRIVILEGE GRANTEE GRANTABLE GRANTOR OBJECT_NAME
EXECUTE SCHEMA_2 NO SCHEMA_1 PAQ_LOCATIONS
In "ESQUEMA_2", I try to execute "PAQ_LOCATIONS":
DECLARE
v_locations SCHEMA_1.PAQ_LOCATIONS.t_TABLE_LOCATIONS;
BEGIN
v_locations := SCHEMA_1.PAQ_LOCATIONS.OBTAIN_ALL ( 6015 );
FOR i IN v_locations.FIRST .. v_locations.LAST
LOOP
DBMS_OUTPUT.put_line ( v_locations (i).DLOCATION );
END LOOP;
END;
Then it throws an exception:
"
Error que empieza en la línea: 1 del comando :
DECLARE
...etc...
END;
ORA-06550: línea 2, columna 27:
PLS-00201: identifier 'SCHEMA_1.PAQ_LOCATIONS' must be declared
ORA-06550: línea 2, columna 27:
PL/SQL: Item ignored
ORA-06550: línea 5, columna 8:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: línea 5, columna 8:
PL/SQL: Statement ignored
ORA-06550: línea 7, columna 22:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: línea 7, columna 8:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
"

Resources