create/declare a sequence in a stored procedure in oracle - oracle

I have a table non_employee with emp_no as the primary key and a package with a procedure to insert in to this table.
I need to be able to autoincrement the emp_no when the procedure is run. I tried creating a sequence within the procedure like this, but getting errors. please see below and advice.
CREATE OR REPLACE PACKAGE BODY WFDDEV."ERD" IS
create SEQUENCE #seq_emp_nmbr;
PROCEDURE INS_NON_EMPLOYEES
(
in_DATE_ADDED DATE,
in_EMPLOYEE_NAME VARCHAR2,
in_DEPT_ID VARCHAR2,
in_SUB_DEPARTMENT VARCHAR2,
in_LOCATION VARCHAR2,
in_WORK_TEL_NO VARCHAR2,
in_TOUR VARCHAR2,
in_REST_DAYS VARCHAR2,
in_HOME_ADDRESS VARCHAR2,
in_CITY VARCHAR2,
in_STATE VARCHAR2,
in_ZIP VARCHAR2,
in_HOME_TEL_NO VARCHAR2,
in_GENDER VARCHAR2,
in_RACE VARCHAR2,
in_DATE_OF_BIRTH DATE,
in_AGE VARCHAR2,
in_HIRE_DATE DATE,
in_UNION_AFFILIATION VARCHAR2,
in_TITLE VARCHAR2,
in_NON_EE_INDICATOR VARCHAR2
) IS
BEGIN
INSERT INTO WFDDEV.NON_EMPLOYEES
(
EMP_NO,
DATE_ADDED,
EMPLOYEE_NAME,
DEPT_ID,
SUB_DEPARTMENT,
LOCATION,
WORK_TEL_NO,
TOUR,
REST_DAYS,
HOME_ADDRESS,
CITY,
STATE,
ZIP,
HOME_TEL_NO,
GENDER,
RACE,
DATE_OF_BIRTH,
AGE,
HIRE_DATE,
UNION_AFFILIATION,
TITLE,
NON_EE_INDICATOR
)
VALUES
(
emp_no.NEXTVAL,
in_DATE_ADDED,
in_EMPLOYEE_NAME,
in_DEPT_ID,
in_SUB_DEPARTMENT,
in_LOCATION,
in_WORK_TEL_NO,
in_TOUR,
in_REST_DAYS,
in_HOME_ADDRESS,
in_CITY,
in_STATE,
in_ZIP,
in_HOME_TEL_NO,
in_GENDER,
in_RACE,
in_DATE_OF_BIRTH,
in_AGE,
in_HIRE_DATE,
in_UNION_AFFILIATION,
in_TITLE,
in_NON_EE_INDICATOR
);
END;
Im getting PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
begin end function pragma procedure subtype type
error with this...

You need to create the sequence just once outside of the package as a separate database object. Then, in the insert statement in your package body you can reference the sequence to get the next value.

Try-
EXECUTE IMMEDIATE 'CREATE SEQUENCE SEQ_NAME START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 1000000 NOCYCLE NOCACHE ORDER';
This should be inside a Procedure or Function body and not in the Declaration section i.e. this should be treated as a executable statement.
Creating a sequence using Dynamic SQL is a bad idea and I am not sure why you would want to do that. However, if you are creating a sequence dynamically then remember to drop it as well after finishing up, using
EXECUTE IMMEDIATE 'DROP SEQUENCE SEQ_NAME';
This way you would atleast not run into errors (like ORA-00955) while calling the package procedure.

Related

PLSQL Procedure to insert employee: ORA-00984

I am trying to insert employee data into employee table from hr database using procedure. I'm getting these errors:
19/5 PL/SQL: SQL Statement ignored
20/72 PL/SQL: ORA-00984: column not allowed here
when I execute this code:
CREATE OR REPLACE PROCEDURE proc_add_new_emp(p_employee_id IN NUMBER,
p_employee_first_name IN VARCHAR2,
p_employee_last_name IN VARCHAR2,
p_employee_email IN VARCHAR2,
p_employee_phone_number IN VARCHAR2,
p_employee_hire_date IN DATE,
p_employee_job_id IN VARCHAR2,
p_employee_salary IN NUMBER,
p_employee_commission_pct IN NUMBER,
p_employee_manager_id IN VARCHAR2,
p_employee_department_id IN VARCHAR2) IS
BEGIN
INSERT INTO employees (employee_id, employee_first_name, employee_last_name, emp_email, employee_phone_number, employee_hire_date, employee_salary, employee_commission_pct, employee_manager_id, employee_department_id)
VALUES(p_employee_id, p_employee_first_name, p_employee_last_name, p_emp_email, p_employee_phone_number, p_employee_hire_date, p_employee_salary, p_employee_commission_pct, p_employee_manager_id, p_employee_department_id);
END;
/
This is the cause of the error:
CREATE OR REPLACE PROCEDURE proc_add_new_emp(
p_employee_id IN NUMBER,
p_employee_first_name IN VARCHAR2,
p_employee_last_name IN VARCHAR2,
p_employee_email IN VARCHAR2, --> this
INSERT INTO employees
(employee_id,
employee_first_name,
employee_last_name,
emp_email,
...)
VALUES
(p_employee_id,
p_employee_first_name,
p_employee_last_name,
p_emp_email, --> and this
If parameter's name is P_EMPLOYEE_EMAIL, then you have to use it in INSERT statement, not P_EMP_MAIL.

Error PLS-00103 when create package with Oracle

I'm trying create package with oracle, although I have read many examples in docs oracle and built code same this tutorial but I still error this.
The following code:
create table manage_emplyee
(
f_name varchar(20),
l_name varchar(20)
);
// Specification
create or replace package fn2
as
procedure manage_emplyee(v_fname in VARCHAR2, v_lname in VARCHAR2);
procedure manage_emplyee_delete(v_fname in VARCHAR2);
end;
/
create or replace package body fn2
as
--Procedure Implementation
procedure manage_emplyee(v_fname in VARCHAR2, v_lname in VARCHAR2)
is
begin
insert into manage_emplyee VALUES (v_lname, v_lname);
end manage_emplyee;
// body
procedure manage_emplyee_delete (v_fname in VARCHAR2)
is
begin
delete manage_emplyee where v_fname = v_fname;
end manage_emplyee_delete;
end fn2;
/
Error
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
begin end function pragma procedure
Please help me fix it, thanks so much !
There are many things incorrect, so here is a correct version.
Run the table script first -
create table manage_emplyee
(
f_name varchar(20),
l_name varchar(20)
);
Run the Spec script after that
create or replace package fn2
as
procedure manage_emplyee(v_fname VARCHAR2,
v_lname VARCHAR2);
procedure manage_emplyee_delete(v_fname VARCHAR2);
end;
/
Run the body script after that
create or replace package body fn2
as
procedure manage_emplyee(v_fname VARCHAR2, v_lname VARCHAR2)
is
begin
insert into manage_emplyee VALUES (v_lname, v_lname);
end ;
procedure manage_emplyee_delete (v_fname VARCHAR2)
is
begin
delete from manage_emplyee where f_name = v_fname;
end ;
end;
/
The syntax for delete from table_name was incorrect.
I am sure, you want to match f_name from table with v_fname from the input variable to delete the data. Earlier you were matching v_fname with v_fname in your code, which will always be true (except for when its passed NULL) and you would end up loosing all your test data
*NOTE -
Adding IN explicitly is not required, the default type is IN for parameters in PLSQL procedures

Oracle Passing Custom Table Type To Stored Procedure

FYI: Oracle 12c
I have created a custom type called Payeezy_Error:
create or replace TYPE PAYEEZY_ERROR
AS
OBJECT (
CODE VARCHAR(30),
DESCRIPTION VARCHAR(200)
);
And then in turn created a Table type of Payeezy_Errors:
create or replace TYPE PAYEEZY_ERRORS AS TABLE OF PAYEEZY_ERROR;
I then have a Procedure that takes Payeezy_Errors as an IN parameter:
create or replace PROCEDURE SAVE_USER_PAYMENT_TRANSACTION
(
in_AccountID IN VARCHAR2,
in_SequenceID IN VARCHAR2,
in_CorrelationID IN VARCHAR2,
in_TransactionID IN VARCHAR2,
in_TransactionTag IN VARCHAR2,
in_Currency IN VARCHAR2,
in_TransactionType IN VARCHAR2,
in_BankResponse IN VARCHAR2,
in_GatewayResponse IN VARCHAR2,
in_ValidationStatus IN VARCHAR2,
in_TransactionStatus IN VARCHAR2,
in_Errors IN PAYEEZY_ERRORS
)
AS
var_uptID NUMBER;
var_ErrorCount NUMBER := 0;
EX_AUTHENTICATION EXCEPTION;
BEGIN
-- Insert the Payeezy Response values tied to the user
INSERT INTO
USER_PAYMENT_TRANSACTION (
ACCOUNT_ID, UP_PAYMENT_SEQ_ID, CORRELATION_ID, TRANSACTION_ID,
TRANSACTION_TAG, CURRENCY, TRANSACTION_TYPE, BANK_RESPONSE,
GATEWAY_RESPONSE, VALIDATION_STATUS, TRANSACTION_STATUS
) VALUES (
in_AccountID, in_SequenceID, in_CorrelationID, in_TransactionID,
in_TransactionTag, in_Currency, in_TransactionType, in_BankResponse,
in_GatewayResponse, in_ValidationStatus, in_TransactionStatus
)
RETURNING
ID
INTO
var_uptID;
-- Insert any errors that may be associated with a failure/unsuccessful transaction
SELECT
COUNT(*)
INTO
var_ErrorCount
FROM
in_Errors;
IF (var_ErrorCount > 0) THEN
INSERT INTO
USER_PAYMENT_TRANSACTION_ERROR (
UPT_ID, CODE, DESCRIPTION
)
SELECT
var_uptID, e.CODE, e.DESCRIPTION
FROM
in_Errors;
END IF;
-- Exception Handling
EXCEPTION
WHEN EX_AUTHENTICATION THEN
raise_application_error(-20001, 'Authentication Failed.');
END SAVE_USER_PAYMENT_TRANSACTION;
When I compile the procedure it yells at me at the SELECT COUNT(*) statement that:
ORA-00942: table or view does not exist.
And red-dashes are under SELECT and in_Errors.
Further down the procedure I get the same error and the second INSERT INTO and in_Errors lines are red-dashes too.
I have exited and reloaded Oracle SQL Developer just to see if it was a caching thing. I have searched around the web but have not found my particular case.
If you want to use the table in a query, you'd need to use the table operator
SELECT
COUNT(*)
INTO
var_ErrorCount
FROM
table( in_Errors );
That works. But it means that you're taking all of the data that you have in the PL/SQL collection, moving it to the SQL VM, doing the aggregation, and then returning the result to PL/SQL. It would likely be more efficient (and less code) in this case to just do
var_ErrorCount := in_Errors.count;

New Oracle Package with Stored Procedure Including Parameters

I am having difficulty with writing my stored procedure within a package. Below is my stored procedure that compiles fine outside of the package, but I believe needs to be written differently within the package body. I admit this is my first time using a package...
create or replace PROCEDURE SP_COMMENT(P_MEMBER_ID IN VARCHAR2, P_MEMBER_LASTNAME IN
VARCHAR2, P_MEMBER_FIRSTNAME IN VARCHAR2, P_MEMBER_STARTDATE IN DATE,
P_MEMBER_ENDDATE IN DATE, P_PRODUCT_CAT_CODE IN VARCHAR2, P_COMMENT IN VARCHAR2,
COMMENT_CURSOR out sys_refcursor)
AUTHID CURRENT_USER
IS
BEGIN
EXECUTE IMMEDIATE
'INSERT INTO TEST
(
MEMBER_ID,
MEMBER_LASTNAME,
MEMBER_FIRSTNAME,
MEMBER_STARTDATE,
MEMBER_ENDDATE,
PRODUCT_CAT_CODE,
COMMENTS
)
VALUES
(
p_member_id,
p_member_lastname,
p_member_firstname,
p_member_startdate,
p_member_enddate,
p_product_cat_code,
p_comment)';
commit;
open COMMENT_CURSOR for select * from sconti.TEST;
END;
Below is the package that I started, and which is not working:
CREATE OR REPLACE
PACKAGE COMMENT_TEST IS
PROCEDURE SP_COMMENT(P_MEMBER_ID IN VARCHAR2, P_MEMBER_LASTNAME IN VARCHAR2,
P_MEMBER_FIRSTNAME IN VARCHAR2, P_MEMBER_STARTDATE IN DATE,
P_MEMBER_ENDDATE IN DATE, P_PRODUCT_CAT_CODE IN VARCHAR2, P_COMMENT IN VARCHAR2,
COMMENT_CURSOR out sys_refcursor) IS
BEGIN
EXECUTE IMMEDIATE
'INSERT INTO TEST
(
MEMBER_ID,
MEMBER_LASTNAME,
MEMBER_FIRSTNAME,
MEMBER_STARTDATE,
MEMBER_ENDDATE,
PRODUCT_CAT_CODE,
COMMENTS
)
VALUES
(
p_member_id,
p_member_lastname,
p_member_firstname,
p_member_startdate,
p_member_enddate,
p_product_cat_code,
p_comment)';
commit;
open COMMENT_CURSOR for select * from sconti.TEST;
END;
END COMMENT_TEST;
I look forward to any response to assist me....thanks!
I can't say for certain (because you haven't shared the error you're getting), but most basic error is a lack of understanding of the specification/body.
You've put the code into the package specification, rather than the body. The specification should just have the procedure declarations (i.e. no begin and end), where as the body has the full content of the procedure.
While it won't affect compilation, there is another problem: the SQL inside the string can't access the parameters supplied to the procedure. If you must use dynamic SQL (and there's absolutely no reason to in this case), then you need a using clause to bind the variable into the dynamic statement. In addition, making the SQL static will allow the SQL statement to be validated at compile-time, which has obvious advantages.
A revised packaged (specification and body) is below.
CREATE OR REPLACE PACKAGE comment_test IS
PROCEDURE sp_comment (p_member_id IN VARCHAR2,
p_member_lastname IN VARCHAR2,
p_member_firstname IN VARCHAR2,
p_member_startdate IN DATE,
p_member_enddate IN DATE,
p_product_cat_code IN VARCHAR2,
p_comment IN VARCHAR2,
comment_cursor OUT SYS_REFCURSOR);
END comment_test;
/
CREATE OR REPLACE PACKAGE BODY comment_test IS
PROCEDURE sp_comment (p_member_id IN VARCHAR2,
p_member_lastname IN VARCHAR2,
p_member_firstname IN VARCHAR2,
p_member_startdate IN DATE,
p_member_enddate IN DATE,
p_product_cat_code IN VARCHAR2,
p_comment IN VARCHAR2,
comment_cursor OUT SYS_REFCURSOR) IS
BEGIN
INSERT INTO test (member_id,
member_lastname,
member_firstname,
member_startdate,
member_enddate,
product_cat_code,
comments)
VALUES (p_member_id,
p_member_lastname,
p_member_firstname,
p_member_startdate,
p_member_enddate,
p_product_cat_code,
p_comment);
COMMIT;
OPEN comment_cursor FOR SELECT * FROM sconti.test;
END;
END comment_test;
/

Concurrency problems with stored procedure

I need help. I have the following stored procedure but I have concurrency problems. Anybody can tell me how to modify the stored procedure to avoid duplicate key error because two users make the same selection at once?. The primary key is the field IDSOLICITUD and the table os SOLIC, that is numeric and I want to insert into this table a counter each time you access it and return that value to the calling application. The structure of the table I can not change, I can not put a AutoNumber.
CREATE procedure PRC_SOLIC(FECHA IN DATE, IDTRAMITE IN VARCHAR2, ESTADO IN NUMBER, ESTADO_FECHA IN DATE, MENSAJE_ERROR IN VARCHAR2, CPROVIN IN NUMBER, CMUNICI IN NUMBER, NHABITA IN NUMBER, NDOMICI IN NUMBER, REFORIGEN IN VARCHAR2,OPERACION_TIPO IN VARCHAR2, OPERACION_CODIGO IN NUMBER, USUARIO IN VARCHAR2, FINALIDAD IN VARCHAR2, RESULTADO IN VARCHAR2,NUM OUT NUMBER) is
v_Numero NUMBER;
CURSOR c_Solic is SELECT MAX(IDSOLICITUD)+1 FROM SOLIC;
BEGIN
OPEN c_Solic;
FETCH c_Solic INTO v_Numero;
IF (v_Numero is NULL) THEN
v_Numero := 1;
END IF;
INSERT INTO SOLIC VALUES (v_Numero, FECHA, IDTRAMITE, ESTADO, ESTADO_FECHA, MENSAJE_ERROR, CPROVIN, CMUNICI, NHABITA,
NDOMICI, REFORIGEN, OPERACION_TIPO, OPERACION_CODIGO, USUARIO, FINALIDAD, RESULTADO);
NUM := v_Numero;
close c_Solic;
END PRC_SOLIC;
Thank you.
Your tags are confusing, is it Oracle or MySQL? If Oracle then look into using sequences for this sort of thing. See Managing Sequences. You can then create a sequence such as:
CREATE SEQUENCE IDSOLICITUD_SEQ
START WITH 1
INCREMENT BY 1;
And then in your code:
CURSOR c_Solic is SELECT IDSOLICITUD_SEQ.NEXTVAL FROM SYS.DUAL;
edit based on being unable to use AutoIncrement
The following assumes you are using MySQL, for Oracle please see the other answer
Seeing as you can't change it to be an AutoIncrement you seem to have to resort to to explicitly locking the table using LOCK TABLES
http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
This gives
CREATE procedure PRC_SOLIC(FECHA IN DATE, IDTRAMITE IN VARCHAR2, ESTADO IN NUMBER, ESTADO_FECHA IN DATE, MENSAJE_ERROR IN VARCHAR2, CPROVIN IN NUMBER, CMUNICI IN NUMBER, NHABITA IN NUMBER, NDOMICI IN NUMBER, REFORIGEN IN VARCHAR2,OPERACION_TIPO IN VARCHAR2, OPERACION_CODIGO IN NUMBER, USUARIO IN VARCHAR2, FINALIDAD IN VARCHAR2, RESULTADO IN VARCHAR2,NUM OUT NUMBER) is
BEGIN
// Declare the variable which will hold the "AI" field
DECLARE thisSolicID INT UNSIGNED DEFAULT 0;
// Lock the table for writing
LOCK TABLES SOLIC WRITE;
// Get the "AI" value
SELECT COALESCE(MAX(IDSOLICITUD),0)+1 INTO thisSolicID FROM FROM SOLIC;
// Insert it
INSERT INTO SOLIC VALUES (thisSolicID, FECHA, IDTRAMITE, ESTADO, ESTADO_FECHA, MENSAJE_ERROR, CPROVIN, CMUNICI, NHABITA, NDOMICI, REFORIGEN, OPERACION_TIPO, OPERACION_CODIGO, USUARIO, FINALIDAD, RESULTADO);
// Unlock the table
UNLOCK TABLES;
END PRC_SOLIC;

Resources