I am attempting my first stored procedure for Oracle because my previous insert statement wasn't working. I get these weird errors that I have been googling for hours on and no one seems to have corrections to my specific issue.
I just want to be able to add records :/
My code is as follows:
CREATE OR REPLACE Insert_classifieds
(val_date IN TABLENAME.Addate%type,
val_category IN TABLENAME.Category%type,
val_user IN TABLENAME.Username%type,
val_ phone IN TABLENAME.Phonenbr%type,
val_email IN TABLENAME.Email%type,
val_shortDes IN TABLENAME.Description%type,
val_longDes IN TABLENAME.Fulldescription%type ,
val_newstandardid out TABLENAME.Classid%type
)
as num_standardid number;
begin
select t_class_seq.nextval into num_standardid from dual;
INSERT INTO TABLENAME (Classid, Addate, Category, Username, Phonenbr, Email, Description, Fulldescription)
VALUES (num_standardid, val_date, val_category, val_user, val_phone, val_email, val_shortDes, val_longDes);
commit;
val_newstandardid := num_standardid;
end;
If you are trying to create a procedure, the syntax is (you were missing the "PROCEDURE" Keyword):
CREATE OR REPLACE PROCEDURE Insert_classifieds
So my issue was that val_phone had a space and a few touch up corrections.
final:
CREATE OR REPLACE PROCEDURE Insert_classifieds
(val_date TABLENAME.Addate%type,
val_category TABLENAME.Category%type,
val_user TABLENAME.Username%type,
val_phone TABLENAME.phonenbr%type,
val_email TABLENAME.Email%type,
val_shortDes TABLENAME.Description%type,
val_longDes TABLENAME.Fulldescription%type)
as num_classid number;
begin
select t_class_seq.nextval into num_classid from dual;
INSERT INTO TABLENAME (Classid, Addate, Category, Username, Phonenbr, Email, Description, Fulldescription)
values (num_classid, val_date, val_category, val_user, val_phone, val_email, val_shortDes, val_longDes);
commit;
end;
Related
I have this simple stored procedure, where it would add a column to my Orders table
create or replace PROCEDURE ADD_ORDER
(
CUSTOMER_ID IN NUMBER
, NEW_ORDER_ID OUT NUMBER
) AS
DECLARE
NEW_ORDER_ID := MAX(ORDERS.ORDER_NO) + 1;
BEGIN
INSERT INTO ORDERS(ORDER_NO, REP_NO, CUST_NO, ORDER_DT, STATUS)
VALUES( NEW_ORDER_ID, 36, CUSTOMER_ID, CURDATE(), 'C')
END ADD_ORDER;
It is saying the the declare part is not at the correct place (I think), and also it should not end there. Here is what it is saying at the error screen:
Error(6,1): PLS-00103: Encountered the symbol "DECLARE" when expecting one of the following:
begin function pragma procedure subtype type current cursor delete exists prior external language The symbol "begin was inserted before "DECLARE" to continue.
Error(11,1): PLS-00103: Encountered the symbol "END" when expecting one of the following: , ; return returning
Can anyone tell me what is going wrong here ?
As has been mentioned, it is a bad idea to select the maximum order number and then use that to insert a row. If two processes do this at the same time, they try to insert rows with the same order number.
Better use Oracle's built-in features SEQUENCE or IDENTITY.
Here is how you could create the table:
CREATE TABLE orders
(
order_no NUMBER(8) GENERATED ALWAYS AS IDENTITY,
rep_no NUMBER(3) DEFAULT 36 NOT NULL,
cust_no NUMBER(8) NOT NULL,
order_dt DATE DEFAULT SYSDATE NOT NULL,
status VARCHAR2(1) DEFAULT 'C' NOT NULL
);
And this is what your procedure would look like then:
CREATE OR REPLACE PROCEDURE add_order
(
in_cust_no IN NUMBER,
out_order_no OUT NUMBER
) AS
BEGIN
INSERT INTO ORDERS(cust_no) VALUES (in_cust_no)
RETURNING order_no INTO out_order_no;
END add_order;
Demo: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=4b49723c15eb810c01077286e171bc95
There is a syntax error in your code.
NEW_ORDER_ID := MAX(ORDERS.ORDER_NO) + 1; --not be used liked it.
Use below code
create or replace PROCEDURE ADD_ORDER
(
CUSTOMER_ID IN NUMBER
, NEW_ORDER_ID OUT NUMBER
) AS
V_NEW_ORDER_ID NUMBER;
BEGIN
SELECT NVL(MAX(ORDER_NO),0)+1 INTO V_NEW_ORDER_ID FROM ORDERS;
INSERT INTO ORDERS(ORDER_NO, REP_NO, CUST_NO, ORDER_DT, STATUS)
VALUES( V_NEW_ORDER_ID, 36, CUSTOMER_ID, CURDATE(), 'C');
NEW_ORDER_ID:=V_NEW_ORDER_ID;
/*
* CURDATE() -> I am assuming it is user defined function. You can also use SYSDATE, CURRENT_DATE istead of CURDATE()
* OUT Parameter is a write-only parameter. You cannot read value from OUT Parameter
*/
END ADD_ORDER;
Few things need to be correct.
If you're expecting to write a PROCEDURE or a FUNCTION you don't have to use the DECLARE keyword. In writing a test script or something, you should use the DECLARE keyword to declare variables.
When writing a procedure,
All the parameters should be inside the brackets.
Variables should define between AS and BEGIN keywords and should give the datatype.
If you need to fetch the MAX number of ORDERS TAB you have to write a SQL query for that. Because the MAX function only can be used inside a SQL. Additionally, if you interest there is an in-built feature call SEQUENCE in ORACLE which can use for NEW_ORDER_ID. You can check with the link below.
adding a sequence for oracle plsql
I did some changes to your code. Hope it's working fine now. Please take a visit here.
CREATE or REPLACE PROCEDURE ADD_ORDER (
CUSTOMER_ID IN NUMBER
NEW_ORDER_ID OUT NUMBER
) AS
CURSOR get_max_order_no IS
SELECT MAX(order_no)
FROM ORDERS;
rec_ NUMBER := 0;
BEGIN
OPEN get_max_order_no;
FETCH get_max_order_no INTO rec_;
CLOSE get_max_order_no;
NEW_ORDER_ID := rec_ + 1;
INSERT INTO ORDERS
(ORDER_NO, REP_NO, CUST_NO, ORDER_DT, STATUS)
VALUES
(NEW_ORDER_ID, 36, CUSTOMER_ID, SYSDATE, 'C');
END ADD_ORDER;
Here I have a question that I need to write a PL/SQL. The structure of the database is also linked. The question requires to use a sequence inside a procedure. I'm new to this and don't know if this works properly and my exec command doesn't seem working please help me out. Also is this how to look up the max shareholder_id that the sequence should start with, or can I a select inside create sequence?
Write a PL/SQL procedure called INSERT_DIRECT_HOLDER which will be used to insert new direct holders. Create a sequence to automatically generate shareholder_ids. Use this sequence in your procedure.
-Input parameters: first_name, last_name
DROP SEQUENCE shareholder_id_seq;
SELECT
MAX(shareholder_id)
FROM shareholder;
CREATE SEQUENCE shareholder_id_seq
INCREMENT BY 1
START WITH 25;
CREATE OR REPLACE PROCEDURE insert_direct_holder(
p_first_name in direct_holder.first_name%type,
p_last_name in direct_holder.last_name%type)
IS
v_shareholder_id NUMBER(6);
BEGIN
INSERT INTO DIRECT_HOLDER(direct_holder_id,first_name,last_name) values(shareholder_id_seq.nextval, p_first_name, p_last_name);
INSERT INTO shareholder (shareholder_id, type) VALUES (shareholder_id_seq.nextval,'Direct_Holder');
COMMIT;
END;
/
/* test command*/
exec insert_direct_holder( p_first_name, p_last_name );
You need to insert the record with same ID in both the tables.
also, you need to insert record into your parent table (shareholder) first and then child table(direct_holder).
CREATE OR REPLACE PROCEDURE insert_direct_holder(
p_first_name in direct_holder.first_name%type,
p_last_name in direct_holder.last_name%type)
IS
v_shareholder_id NUMBER(6);
BEGIN
v_shareholder_id := shareholder_id_seq.nextval;
INSERT INTO shareholder (shareholder_id, type) VALUES (v_shareholder_id,'Direct_Holder');
INSERT INTO DIRECT_HOLDER(direct_holder_id,first_name,last_name) values(v_shareholder_id, p_first_name, p_last_name);
COMMIT;
END;
/
/* test command*/
exec insert_direct_holder( p_first_name, p_last_name );
Sequence is created once to implement auto incrementing feature for any numeric column.
For the current use case it has to be created just once and left forever hopefully.Sequence can be modified in future if required.
If shareholder table has records in it already, then create the sequence with start value as SELECT MAX(shareholder_id) + 1 FROM shareholder; to avoid primary key constraint violation.
A slight modification is required for the stored procedure to use the same SHAREHOLDER.SHAREHOLDER_ID as the column has foreign key relationship with DIRECT_HOLDER.
Use INSERT ALL to insert to both the tables for the same sequence.nextval.
CREATE OR REPLACE PROCEDURE insert_direct_holder(
p_first_name in direct_holder.first_name%type,
p_last_name in direct_holder.last_name%type)
IS
BEGIN
INSERT ALL
INTO SHAREHOLDER
(shareholder_id, type) values(shareholder_id_seq.nextval,'Direct_Holder')
INTO DIRECT_HOLDER
(direct_holder_id,first_name,last_name) values
(shareholder_id_seq.nextval,p_first_name,p_last_name)
SELECT 'DUMMY' FROM dual;
COMMIT;
END;
/
dbfiddle demo with working code : https://dbfiddle.uk/?rdbms=oracle_18&fiddle=5d80488fb69d78d4b5087f06a5becf96
I'm having a lot of trouble trying to work this out. Essentially, I'm trying to create a procedure in Oracle SQL Developer which enables two books to be lent out to a borrower. The tables and values are correctly setup. I feel like my created procedure may be pretty close (on the right track), but I get confused about the syntax, especially with the dates and when trying to call the procedure.
There are a few other related tables in the schema, but the gist is I'm trying to insert library/borrower records into a table called loan. The values being inserted are: 2x isbn, branchid, cardno, dateout (when book/s are borrowed) and datein (null by default, until book/s are returned). These are the column names in the loan table.
This is the procedure I've been working on:
create or replace procedure BorrowTwoBooks(
p_isbn in varchar2,
p_isbn2 in varchar2,
p_branchid in number,
p_cardno in number
)
is
pDate Date Default SysDate;
begin
insert into loan values(p_isbn, p_branchid, p_cardno, pDate, null);
insert into loan values(p_isbn2, p_branchid, p_cardno, pDate, null);
end BorrowTwoBooks;
and this is an example of how I'd try to call the procedure once it's created:
begin
BorrowTwoBooks(
'9-9996751-3-1','1','489',pDate);
'1-8744165-3-2','1','489',pDate);
end;
where I'm hoping the syntax would be:
begin
BorrowTwoBooks(
'[isbn1],'[branchid],[cardno],[dateout]);
'[isbn2],'[branchid],[cardno],[dateout]);
end;
Any help would be greatly appreciated. This is my first post, thanks everyone in advance for the help. :)
for your procedure the syntax would be:
begin
BorrowTwoBooks([isbn1],[isbn2],[branchid],[cardno]);
end;
try to call:
begin
BorrowTwoBooks('9-9996751-3-1','1-8744165-3-2','1','489');
end;
Yoc created procedure that takes 4 parameters. Two of them are ISBNs of books and two others are common for both books so call should look like:
begin
BorrowTwoBooks(
'9-9996751-3-1','1-8744165-3-2',1,489);
end;
Also date is not a parameter of function. You set it to sysdate when procedure called.
You already got the answer regarding the specific case, but it seems to me that you want a procedure that have date as a parameter that is sysdate by default, but can be populated with some other date if needed.
If this is the case, your procedure should look like this:
create or replace procedure BorrowTwoBooks(
p_isbn in varchar2,
p_isbn2 in varchar2,
p_branchid in number,
p_cardno in number,
p_date in date default sysdate)
is
begin
insert into loan(isbn, branchid, cardno, dateout, datein)
values(p_isbn, p_branchid, p_cardno, p_date, null);
insert into loan(isbn, branchid, cardno, dateout, datein)
values(p_isbn2, p_branchid, p_cardno, p_date, null);
end BorrowTwoBooks;
You can call it without providing date:
begin
BorrowTwoBooks('9-9996751-3-1', '1-8744165-3-2', '1', '489');
end;
Or you can call it with the specific date:
declare
l_date date;
begin
l_date := to_date('2016/10/05', 'yyyy/mm/dd');
BorrowTwoBooks('9-9996751-3-1', '1-8744165-3-2', '1', '489', l_date);
end;
There is another way to call the procedure - by providing parameter names. This syntax may be easier for you to understand:
begin
BorrowTwoBooks(p_isbn => '9-9996751-3-1',
p_isbn2 => '1-8744165-3-2',
p_branchid => '1',
p_cardno => '489');
end;
I have the following code which produces a few compiler errors. I've followed several examples online to use these declare and the FROM DUAL concepts, but can't ID the problem. Thanks!
Error1: SQL statement Ignored (referencing line 9 - "DECLARE")
Error2: missing VALUE keyword (referencing line 15 - "FROM DUAL;")
---delete or replace trigger------------------------------
CREATE OR REPLACE TRIGGER videoAuditDeleteTrigger
BEFORE DELETE OR UPDATE
ON video
FOR EACH ROW
DECLARE
v_username VARCHAR2(20);
BEGIN
SELECT USER INTO v_username
FROM DUAL;
INSERT INTO videoAudit
(videoID
,title
,releaseDate
,category
,username
,datetimestamp);
VALUES
(:OLD.videoID
,:OLD.title
,:OLD.releaseDate
,:OLD.category
,v_username
,SYSDATE);
END;
/
Try this, you used extra semicolon in insert statement
CREATE OR REPLACE TRIGGER videoAuditDeleteTrigger
BEFORE DELETE OR UPDATE ON video FOR EACH ROW
DECLARE v_username VARCHAR2(20);
BEGIN
SELECT USER INTO v_username FROM DUAL;
INSERT INTO videoAudit (videoID ,title ,releaseDate ,category ,username ,datetimestamp)
VALUES (:OLD.videoID ,:OLD.title ,:OLD.releaseDate ,:OLD.category ,v_username ,SYSDATE);
END;
I have this procedure
PROCEDURE insertSample
(
return_code_out OUT VARCHAR2,
return_msg_out OUT VARCHAR2,
sample_id_in IN table1.sample_id%TYPE,
name_in IN table1.name%TYPE,
address_in IN table1.address%TYPE
)
IS
BEGIN
return_code_out := '0000';
return_msg_out := 'OK';
INSERT INTO table1
sample_id, name, address)
VALUES
(sample_id_in, name_in, address_in);
EXCEPTION
WHEN OTHERS
THEN
return_code_out := SQLCODE;
return_msg_out := SQLERRM;
END insertSample;
I want to add 4th column in table1 like day_time and add current day timestamp in it.. ho can i do that in this procedure.. thank you
Assuming you you have (or add) a column to the table outside of the procedure, i.e.
ALTER TABLE table1
ADD( insert_timestamp TIMESTAMP );
you could modify your INSERT statement to be
INSERT INTO table1
sample_id, name, address, insert_timestamp)
VALUES
(sample_id_in, name_in, address_in, systimestamp);
In general, however, I would strongly suggest that you not return error codes and error messages from procedures. If you cannot handle the error in your procedure, you should let the exception propagate up to the caller. That is a much more sustainable method of writing code than trying to ensure that every caller to every procedure always correctly checks the return code.
Using Sysdate can provide all sorts of manipulation including the current date, or future and past dates.
http://edwardawebb.com/database-tips/sysdate-determine-start-previous-month-year-oracle-sql
SYSDATE will give you the current data and time.
and if you add the column with a default value you can leave your procedure as it is
ALTER TABLE table1 ADD when_created DATE DEFAULT SYSDATE;