Solved

PLS-00201: identifier 'ADD_ORDER' must be declared

Posted on 2008-10-11
22
2,895 Views
Last Modified: 2013-12-18
Hi Experts:
I am taking Oracle at school and I cannot figure out why my stored package\procedure is coming bak with "PLS-00201: identifier 'ADD_ORDER' must be declared". I am ruuning this locally on SGL PLUS, Oracle 10g, My code is listed below,
Thanks!

Kevin


CREATE OR REPLACE PACKAGE Process_Orders AS

	PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,

			p_eno IN orders.eno%TYPE,

			p_received IN OUT orders.received%TYPE);

			p_creation_date DATE;

			p_last_update_date DATE;

			p_created_by VARCHAR2(10);

			p_last_update_by VARCHAR2(10);	

 

END Process_Orders;

/

show errors

set echo on

 

DROP SEQUENCE Order_number_seq;

CREATE SEQUENCE Order_number_seq

    MINVALUE 1

    MAXVALUE 1000000

    START WITH 1

    INCREMENT BY 1;

 

CREATE OR REPLACE PACKAGE BODY Process_Orders AS

  -- Add a new order for the specified class.

  -- Order_number_seq should be used to populate the order number (ONO) column.

	PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,

			p_eno IN orders.eno%TYPE,

			p_received IN OUT orders.received%TYPE) AS

	BEGIN

	IF p_received = NULL

		THEN p_received := CURRENT_DATE;

	END IF;

 

	SELECT user INTO p_created_by FROM dual;

	SELECT user INTO p_last_update_by FROM dual;

	

	INSERT INTO orders (ono,cno,eno,received,creation_date,created_by,last_update_date,last_update_by)

			VALUES (Order_number_seq.NextVal,p_cno,p_eno,p_received, p_creation_date,

				p_created_by,p_last_update_date,p_last_update_by );

	

	--Exception Handler:

	  EXCEPTION

    		WHEN DUP_VAL_ON_INDEX THEN

      			DBMS_OUTPUT.PUT_LINE('ERROR - Unique Constraint Violation: ' || SQLERRM);

    		WHEN OTHERS THEN

      			DBMS_OUTPUT.PUT_LINE('Undentified error occured: ' || SQLERRM); 

END Add_Order;

 

END Process_Orders;

/

 

show errors

Open in new window

0
Comment
Question by:k_smee
  • 11
  • 9
  • 2
22 Comments
 
LVL 73

Expert Comment

by:sdstuber
Comment Utility
can you show you show your entire output from running all of the above?  
0
 

Author Comment

by:k_smee
Comment Utility
Here is what I get in the SQL PLUS starting with running the stored procedure and then trying to execute it:
SQL> @Pack.sql

SQL> CREATE OR REPLACE PACKAGE Process_Orders AS

  2          PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,

  3                          p_eno IN orders.eno%TYPE,

  4                          p_received IN OUT orders.received%TYPE);

  5                          p_creation_date DATE;

  6                          p_last_update_date DATE;

  7                          p_created_by VARCHAR2(10);

  8                          p_last_update_by VARCHAR2(10);

  9  

 10  END Process_Orders;

 11  /
 

Package created.
 

SQL> show errors

No errors.

SQL> set echo on

SQL> 

SQL> DROP SEQUENCE Order_number_seq;
 

Sequence dropped.
 

SQL> CREATE SEQUENCE Order_number_seq

  2      MINVALUE 1

  3      MAXVALUE 1000000

  4      START WITH 1

  5      INCREMENT BY 1;
 

Sequence created.
 

SQL> 

SQL> CREATE OR REPLACE PACKAGE BODY Process_Orders AS

  2    -- Add a new order for the specified class.

  3    -- Order_number_seq should be used to populate the order number (ONO) column.

  4  

  5  

  6          PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,

  7                          p_eno IN orders.eno%TYPE,

  8                          p_received IN OUT orders.received%TYPE) AS

  9          BEGIN

 10          IF p_received = NULL

 11                  THEN p_received := CURRENT_DATE;

 12          END IF;

 13          SELECT user INTO p_created_by FROM dual;

 14          SELECT user INTO p_last_update_by FROM dual;

 15          INSERT INTO orders (ono,cno,eno,received,creation_date,created_by,last_update_date,last_u

 16                          VALUES (Order_number_seq.NextVal,p_cno,p_eno,p_received, p_creation_date,

 17                                  p_created_by,p_last_update_date,p_last_update_by );

 18  

 19  END Add_Order;

 20  

 21  END Process_Orders;

 22  /
 

Package body created.
 

SQL> 

SQL> show errors

No errors.

SQL> 

SQL> execute Add_Order(10,12,'23-OCT-08');

BEGIN Add_Order(10,12,'23-OCT-08'); END;
 

      *

ERROR at line 1:

ORA-06550: line 1, column 7:

PLS-00201: identifier 'ADD_ORDER' must be declared

ORA-06550: line 1, column 7:

PL/SQL: Statement ignored
 
 

SQL> 

Open in new window

0
 
LVL 42

Accepted Solution

by:
dqmq earned 50 total points
Comment Utility
Try explicitly referencing the package.  I believe, like this:

execute Process_Orders.Add_Order(10,12,'23-OCT-08');

0
 
LVL 73

Expert Comment

by:sdstuber
Comment Utility
yes, the problem isn't in compiling the procedure it's in calling it and, as noted,  you must reference the package to call it's members
0
 

Author Comment

by:k_smee
Comment Utility
This is looking alot better, but I am getting a new problem - a small one I think. See the code snippet. Did I write this part correctly?

p_received IN OUT orders.received%TYPE);



SQL> execute Process_Orders.Add_Order(10,12,'23-OCT-08');

BEGIN Process_Orders.Add_Order(10,12,'23-OCT-08'); END;
 

                                     *

ERROR at line 1:

ORA-06550: line 1, column 38:

PLS-00363: expression '23-OCT-08' cannot be used as an assignment target

ORA-06550: line 1, column 7:

PL/SQL: Statement ignored

Open in new window

0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
It's difficult to advise because we don't know what your procedure is supposed to do.  But here is the issue.

An OUT parameter is intended to pass data from the procedure back to the caller.   Obviously, you cannot do that when the argument passed from the caller is a literal.

You should always pass OUT parameters in variables.  





0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
It's difficult to advise because we don't know what your procedure is supposed to do.  But here is the issue.

An OUT parameter is intended to pass data from the procedure back to the caller.   Obviously, you cannot do that when the argument passed from the caller is a literal.

You should always pass OUT parameters in variables.  





0
 

Author Comment

by:k_smee
Comment Utility
It is supposed enter an order in the ORDERS table. If the date parameter of Add_Order() is NULL (no date entered) use the current date for the date received.
0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
Then change it from IN OUT to IN.  You understand the difference, right?
0
 

Author Comment

by:k_smee
Comment Utility
I changed from IN OUT to IN, but I can't seem to get the procedure to test the p_received for a "zero length" string or NULL. How can I test p_received for zero length? I tried "IF p_received = NULL OR LENGTH(p_received) < 1" and this didn't work. See belowfor my current effort:
 CREATE OR REPLACE PACKAGE Process_Orders AS

	PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,

			p_eno IN orders.eno%TYPE,

			p_received IN DATE);

			p_creation_date DATE;

			p_last_update_date DATE;

			p_created_by VARCHAR2(10);

			p_last_update_by VARCHAR2(10);

			p_date DATE;	
 

END Process_Orders;

/

show errors

set echo on
 

DROP SEQUENCE Order_number_seq;

CREATE SEQUENCE Order_number_seq

    MINVALUE 1

    MAXVALUE 1000000

    START WITH 1

    INCREMENT BY 1;
 

CREATE OR REPLACE PACKAGE BODY Process_Orders AS

  -- Add a new order for the specified class.

  -- Order_number_seq should be used to populate the order number (ONO) column.
 
 

	PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,

			p_eno IN orders.eno%TYPE,

			p_received IN DATE) AS

	BEGIN

-- here is whre i am stuck now

	IF LENGTH(p_received) < 2 

		THEN p_date := CURRENT_DATE;

	ELSE

		p_date := p_received;

	END IF;
 

	SELECT user INTO p_created_by FROM dual;

	SELECT user INTO p_last_update_by FROM dual;

	p_creation_date := CURRENT_DATE;

	p_last_update_date := CURRENT_DATE;

	INSERT INTO orders (ono,cno,eno,received,creation_date,created_by,last_update_date,last_update_by)

			VALUES (Order_number_seq.NextVal,p_cno,p_eno,p_date, p_creation_date,

				p_created_by,p_last_update_date,p_last_update_by );
 

END Add_Order;
 

END Process_Orders;

/
 

show errors

			

Open in new window

0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
Given this is a school assignment, I cannot do your work.  But here's a clue:

'p_received IN DATE' means that p_received is a DATE, not a STRING.  Therefore, it cannot contain a zero-length string.  
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 

Author Comment

by:k_smee
Comment Utility
So I might be able to convert to a string and test it then?
0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
Why to you want to test it for a zero-length string if it cannot contain a zero-length string?  If it cannot contain a zero-length string before you convert it, then it will not contain one after you convert it.

A DATE can only contain two things:  a date and null.  
0
 

Author Comment

by:k_smee
Comment Utility
When I excute this: execute Process_Orders.Add_Order(15,21,''); The procedure does not recognize this as a NULL in the IF statement; it goes straight to the ELSE branch. Our requirement is that if the date is NULL, we use the cuurent date for the "received" date. It thought this IF statement would work fine:

  IF p_received = NULL
          THEN p_date := CURRENT_DATE;
  ELSE
          p_date := p_received;
  END IF;

The way it works now is that it either enters a NULL, if nothing is entered in Add_Orders(), or the date, if one entered in the Add_Orders().
0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
I see. I'm amused.  Learn this lesson well.

To illustrate your problem, change the code like this:

 IF p_received = NULL
          THEN p_date := '06/06/2006';
 ELSE
 IF p_received <> NULL
          THEN p_date := '07/07/2007';
 ELSE
         p_date := '08/08/2008';
 END IF;
 END IF;


Now test with NULL, '', and a valid date

0
 

Author Comment

by:k_smee
Comment Utility
Ok..I had to take some of the literals out and replace them with variables to get the desired result I left the <> NULL as a literal. Here is what I have:
      BEGIN
       IF p_received = NULL
          THEN p_date := CURRENT_DATE;
       ELSE
       IF p_received <> NULL
          THEN p_date := '30-OCT-08';
       ELSE
         p_date := CURRENT_DATE;
       END IF;
       END IF;
The "IF p_received = NULL" piece always evaluates to "p_date = CURRENT_DATE". So wether I enter a date or not I get the current date inserted into the record...
0
 

Author Closing Comment

by:k_smee
Comment Utility
As for your last comment, "I am amused.", I am not; and not sure why you would be. An online class is a very tough environment to learn a technical subject. Thanks for he help with this problem, it definitely made a difference..
0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
The purpose of my example was a test so you could tell which leg of the IF statement got exercised. By using Current_Date on two legs, you sort of defeat the purpose.  

Please bear with me, because there is a very important lesson to be learned.  I do not think you grasp it yet.

The above code falls thru to p_date := CURRENT_DATE.  That happens regardless of what is passed in p_received.

The reason is because NULL is neither equal nor unequal to anything.  Even these expressions are false:
  IF NULL = NULL
  IF NULL <> NULL

To evaluate whether a variable contains NULL, you must use the ISNULL function.  Instead of this:
   IF p_received = NULL

Do this:
   IF ISNULL(p_received)

You should discover that a DATE variable cannot hold ''.  When you try to pass '' in a DATE argument, it gets implicitly converted to NULL.  However, you fail to detect the NULL date because the way you are testing p_received ALWAYS evaluates to false, regardless of what it contains.

To summarize,  you should have learned:
1.  A DATE variable can only hold two things:  a date and NULL.
2.  When you assign '' to a DATE variable, it implicitly gets cast as NULL
3.  NULL is not equal to anything, including itself
4.  To test for NULL, use the ISNULL() function, not the traditional  =<> operators.









 




 







 





0
 

Author Comment

by:k_smee
Comment Utility
Thanks for the clarification on this. I tried a lot of things to test for NULL before  - and I think ISNULL() was one of them. Do you have to somehow delare the Oracle function before you use it? When I try to use ISNULL(p_received) I get:

Errors for PACKAGE BODY PROCESS_ORDERS:

LINE/COL ERROR
-------- -----------------------------------------------------------------
10/3     PL/SQL: Statement ignored
10/6     PLS-00201: identifier 'ISNULL' must be declared
SQL>
SQL>
0
 

Author Comment

by:k_smee
Comment Utility
It works if I do:
IF p_received IS NULL
THEN <do something>
Here is the working product:

CREATE OR REPLACE PACKAGE Process_Orders AS
      PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,
                  p_eno IN orders.eno%TYPE,
                  p_received IN DATE);
                  p_creation_date DATE;
                  p_last_update_date DATE;
                  p_created_by VARCHAR2(10);
                  p_last_update_by VARCHAR2(10);      
                  p_date DATE;
END Process_Orders;
/
show errors
set echo on

DROP SEQUENCE Order_number_seq;
CREATE SEQUENCE Order_number_seq
    MINVALUE 1
    MAXVALUE 1000000
    START WITH 1
    INCREMENT BY 1;

CREATE OR REPLACE PACKAGE BODY Process_Orders AS
  -- Add a new order for the specified class.
  -- Order_number_seq should be used to populate the order number (ONO) column.


      PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,
                  p_eno IN orders.eno%TYPE,
                  p_received IN DATE) AS
      BEGIN
       IF p_received IS NULL
                           THEN p_date := CURRENT_DATE;
       ELSE p_date := p_received;
                      END IF;

      SELECT user INTO p_created_by FROM dual;
      SELECT user INTO p_last_update_by FROM dual;
      p_creation_date := CURRENT_DATE;
      p_last_update_date := CURRENT_DATE;
      INSERT INTO orders (ono,cno,eno,received,creation_date,created_by,last_update_date,last_update_by)
                  VALUES (Order_number_seq.NextVal,p_cno,p_eno,p_date, p_creation_date,
                        p_created_by,p_last_update_date,p_last_update_by );
      COMMIT;

END Add_Order;

END Process_Orders;
/


0
 
LVL 42

Expert Comment

by:dqmq
Comment Utility
My mistake, for ORACLE, use IS NULL not the ISNULL() function.  Now your logic is looking much better.

What do you of streamlining, like this:


 




 PROCEDURE Add_Order(p_cno IN orders.cno%TYPE,

                  p_eno IN orders.eno%TYPE,

                  p_received IN DATE) AS

  BEGIN

  INSERT INTO orders (ono,cno,eno,received,creation_date,created_by,last_update_date,last_update_by)

  SELECT Order_number_seq.NextVal,p_cno,p_eno,NVL(p_date,CURRENT_DATE),CURRENT_DATE,USER,CURRENT_DATE,USER FROM DUAL;

  COMMIT;
 

END Add_Order;

Open in new window

0
 

Author Comment

by:k_smee
Comment Utility
That works great! Much simpler, too. I like how you used the NVL() function to eliminate the IF..
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Join & Write a Comment

Cursors in Oracle: A cursor is used to process individual rows returned by database system for a query. In oracle every SQL statement executed by the oracle server has a private area. This area contains information about the SQL statement and theā€¦
From implementing a password expiration date, to datatype conversions and file export options, these are some useful settings I've found in Jasper Server.
This video explains at a high level about the four available data types in Oracle and how dates can be manipulated by the user to get data into and out of the database.
This videos aims to give the viewer a basic demonstration of how a user can query current session information by using the SYS_CONTEXT function

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now