Solved

PLS-00201: identifier 'ADD_ORDER' must be declared

Posted on 2008-10-11
22
2,905 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
ID: 22694424
can you show you show your entire output from running all of the above?  
0
 

Author Comment

by:k_smee
ID: 22694457
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
ID: 22694519
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
ID: 22694523
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
ID: 22694534
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
ID: 22694590
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
ID: 22694626
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
ID: 22694648
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
ID: 22694923
Then change it from IN OUT to IN.  You understand the difference, right?
0
 

Author Comment

by:k_smee
ID: 22694947
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
ID: 22694980
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
ID: 22694992
So I might be able to convert to a string and test it then?
0
 
LVL 42

Expert Comment

by:dqmq
ID: 22695015
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
ID: 22695048
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
ID: 22695106
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
ID: 22696056
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
ID: 31505318
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
ID: 22698070
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
ID: 22698149
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
ID: 22698214
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
ID: 22698306
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
ID: 22698401
That works great! Much simpler, too. I like how you used the NVL() function to eliminate the IF..
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Subquery in Oracle: Sub queries are one of advance queries in oracle. Types of advance queries: •      Sub Queries •      Hierarchical Queries •      Set Operators Sub queries are know as the query called from another query or another subquery. It can …
Working with Network Access Control Lists in Oracle 11g (part 2) Part 1: http://www.e-e.com/A_8429.html Previously, I introduced the basics of network ACL's including how to create, delete and modify entries to allow and deny access.  For many…
This video explains at a high level with the mandatory Oracle Memory processes are as well as touching on some of the more common optional ones.
Via a live example show how to connect to RMAN, make basic configuration settings changes and then take a backup of a demo database

929 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

14 Experts available now in Live!

Get 1:1 Help Now