I use a dataset that has billing information:
Table Image
And I want to create a procedure that gives information about a specific bill by giving an invoice id
CREATE OR REPLACE PROCEDURE print_information(
invoiceID varchar(11);
) IS
p_smtable supermarket%ROWTYPE;
BEGIN
SELECT * INTO p_smtable FROM SUPERMARKET
WHERE invoice_id = invoiceID;
DBMS_OUTPUT.PUT_LINE(p_smtable.brancj || p_smtable.city);
END;
The compilation is successful.
Compile
begin
print_information('750-67-8428');
end;
But I get an error that says:
Error starting at line : 12 in command -
begin
print_information('750-67-8428');
end;
Error report -
ORA-06550: line 2, column 1:
PLS-00905: object SYSTEM.PRINT_INFORMATION is invalid
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The code in the screenshot is different to the version in your question, but both have an error at line 2. The parameter should be varchar2 or supermarket.invoice_id%type, with no semicolon.
Also, we normally use a p_ prefix for parameters, not variables. (There are other conventions, but whatever you use, p_ for a variable is just confusing.)
A fixed version might be:
create or replace procedure print_information
( p_invoice_id supermarket.invoice_id%type )
as
l_market supermarket%rowtype;
begin
select * into l_market
from supermarket
where invoice_id = p_invoice_id;
dbms_output.put_line(l_market.brancj || ' '|| l_market.city);
end;
Whatever tool you are using for development, you need to become familiar with how to display compilation errors.
brancj might be a typo for branch.
I've assumed you want a space between branch and city, otherwise the output would be something like TottenhamLondon rather than Tottenham London.
In Oracle a schema belongs to one user, created with the CREATE USER command. An Oracle Database is the entire thing (all users, all data, storage, memory, processes, everything) so you would not normally create one for something like this.
Related
I am in a position which requires I pull data to my primary database through a daisy chained dblink set up similar to what is described in this answer
DBLINK_SERVER2 -> SYNONYM -> DBLINK_SERVER3
The synonym is set up on server 2 like this:
CREATE OR REPLACE SYNONYM "MY_USER"."THE_VIEW" FOR "THE_VIEW"#"DBLINK_SERVER3"
When I run a simple select statement from server 1, it works fine and pulls back exactly what i'd expect from server 3's view:
SELECT COUNT(*) FROM THE_VIEW#DBLINK_SERVER2;
However, whenever I try to run code in an anonymous block any reference to the dblink will cause a "looping chain of synonyms" error.
DECLARE
testnum VARCHAR2(50);
BEGIN
SELECT COUNT(*) INTO testnum FROM THE_VIEW#DBLINK_SERVER2;
END;
/
Error report -
ORA-06550: line 2, column 22:
PL/SQL: ORA-01775: looping chain of synonyms
ORA-06550: line 2, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
There aren't any synonyms on server 1 that i can see which reference the view or dblink. If i run this same test on server 2 both the simple command and block work fine when i use the synonym. Any idea why the block fails on server 1 but not if i run the same thing outside of the block? Is this some kind of permissions problem?
*** Edit ***
We never determined what was causing this, but the DBA changed it so that we were referencing a view in server 2 instead of a symlink. That resolved our problem.
CREATE VIEW THE_VIEW AS SELECT * FROM THE_VEW#DBLINK_SERVER3
I come from a SQL Server background but I'm struggling with this in Oracle. All of the sprocs in the database that's been configured expect a parameter passed in of type 'sys_refcursor'. In a nutshell, they do this (the sprocs are far more complex, but the whole cursor thing is what I'm getting at) :
CREATE OR REPLACE PROCEDURE xxx_API_TEST
(
TESTCURSOR OUT SYS_REFCURSOR
) AS
BEGIN
OPEN CURS FOR
SELECT * FROM SOMETABLE;
END xxx_API_TEST;
So - in Oracle SQL Developer I can run this no problem - and view the output of the cursor in the Output Variables window.
However, rather than have to keep reloading the dialog each time I want to retest it - I figured it'd be possible to copy the PL/SQL in the dialog to a new worksheet, and then just run that as I needed to - adjusting parameters to suit - so in this case, I'd run :
DECLARE
TESTCURSOR SYS_REFCURSOR;
BEGIN
xxx_API_TEST(
TESTCURSOR => TESTCURSOR
);
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('TESTCURSOR = ' || TESTCURSOR );
*/
:TESTCURSOR := TESTCURSOR; --<-- Cursor
--rollback;
END;
Which is exactly the same as that shown in the Run dialog.
However, if I do this - it just throws an error - stating:
Error starting at line : 1 in command -
<snip>
Error report -
ORA-06550: line 11, column 20:
PLS-00382: expression is of wrong type
ORA-06550: line 11, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I've no idea how to go about diagnosing this one. The fact it runs fine from the dialog but not the worksheet is puzzling - and inspecting what was sent to the DB I can't see any differences in the SQL it actually used.
Interestingly if I run this code from the worksheet - it pops up a dialog to ask for the value for TESTCURSOR - which the 'Run' dialog doesn't do. I just press OK - but I've tried both ticking and unticking the 'Null' checkbox to no avail.
Any help very much appreciated. It's Oracle 12c. If you need any more info just let me know.
Cheers,
Tony
Update: 20/7/2016
I ended up pulling the values into variables from a fetch, and just dumping to dbms_output - which gives me what I needed to repeatedly run the same sproc.
e.g.
loop
fetch testcursor into Res, ActDate<snip>;
exit when testcursor%notfound;
DBMS_OUTPUT.PUT_LINE(Res || ' | ' || ActDate etc etc);
end loop;
close testcursor;
The Run dialog is generated from the procedure spec and therefore knows the correct type for testcursor, but when you just paste it into a worksheet it doesn't, and it seems to define it as a text string. As of SQL Developer 4.0.3.16 the worksheet bind value prompt doesn't seem to have a way to change the datatype.
As for how to create a reusable test script with a cursor output in SQL Dev, I don't know. (I normally use PL/SQL Developer which can do this, but it's not free software.)
Edit: in this thread a solution was to write a wrapper function and select it from dual. I've just tried and you don't get a grid, but you get a kind of debug output without too much effort:
Oracle SQL Developer: Show REFCURSOR Results in Grid?
I have a schema A, Package B and Procedure C. B is in A schema and C is in B's Package Body.
It works fine when I say:
Begin
Exec B.C;
END;
But it throw an error when I say:
Begin
Exec A.B.C;
END;
Error report:
ORA-06550: line 2, column 12:
PLS-00302: component 'B' must be declared
ORA-06550: line 2, column 4:
PL/SQL: Statement ignored
I log in as A so it's in A's schema.
and
SELECT * FROM user_OBJECTS WHERE OBJECT_NAME = 'B';
shows package and package body both valid.
I had the same problem and found the issue. I will write here the answer to close this problem and help other people.
In my case, my user A have execute privilege on a procedure B(just a procedure, not a package, but it's the same). When the user tries to run:
Begin
Exec A.B;
END;
Get the error:
ERROR at line 2:
ORA-06550: line 2, column 7:
PLS-00302: component 'B' must be declared
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
Problem: That's because a public synonym with name A was created in the database. This is an old database and I am just the DBA, not the developer, but in this case the developer was an uninspired developer. He used 4 types of objects with the same name: user, table, tablespace and public synonym. A public synonym named A in front of a table named A.
Solution: Because you don't know exactly who is using that public synonym I had to found another solution instead of deleting the public synonym. I created a private synonym for that procedure. Now the user can skip the owner of procedure in the execution code and ignore the public synonym. This problem appears in Oracle Database 10.2.0.4.
Begin
Exec B;
END;
PL/SQL procedure successfully completed.
Conclusion: Never use a public/private synonym with the name of the schema.
Hope to help someone. If I didn't made myself clear, please leave a comment.
Fix syntax error in the package, this is a generic PL/SQL compile error message.
Check error points (line 2, column 12) in the PL/SQL where the syntax error occurred, correct it and then try recompiling your code.
Component 'B' must be declared.
After that grant EXECUTE_CATALOG_ROLE to allow user 'A' execute privileges for packages and procedures in the data dictionary.
grant EXECUTE_CATALOG_ROLE to A;
I not family with PL/SQL. Can anyone explain why I can't do the following?
BEGIN
IF TRUE THEN
CREATE INDEX TestIndex ON SomeTable (SomeColumn);
END IF;
END;
I would get the following error:
Error report:
ORA-06550: line 3, column 5:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
begin case declare exit for goto if loop mod null pragma
raise return select update while with
<<
close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The only way I can by pass this error is do dynamic sql:
BEGIN
IF TRUE THEN
EXECUTE IMMEDIATE 'CREATE INDEX TestIndex ON SomeTable (SomeColumn)';
END IF;
END;
Oracle doesn't allow DDL in a PL/SQL block as static SQL so you've identified the only workaround (well, technically, you could use DBMS_SQL rather than EXECUTE IMMEDIATE but you'd still be dealing with dynamic SQL).
I don't know that there is any technical reason that they couldn't allow DDL in static SQL. But since 99% of the time you shouldn't be doing DDL in a stored procedure-- creating objects is something that would almost exclusively be done when you're doing a deployment rather than at runtime-- forcing people to use dynamic SQL makes developers pause to consider whether they're really in that 1% of cases where such a thing makes sense.
The message that drives me crazy is ORA-01008 - Not all variables bound.
Is there a way to know which one of the 42 possible variable names I have misspelled without staring at the monitor till my eyes pop out?
Update: I use ADO.NET to access the database. Perhaps it does lose some information in Oracle exceptions, as #Justin Cave has suggested. But I'm positive that the parameter name never appears even in SQL Plus.
In general, Oracle provides the line and column number of any errors, but it is up to the particular API you are using (unless you happen to be writing an OCI application, which is probably unlikely) as to whether and how those APIs are called. Since the answer is likely to end up being API-specific, what API are are you using and what does your code look like when the error occurs (i.e. JDBC, ODBC, OLE DB, etc)?
As an example, if I write a PL/SQL block with a misspelled variable name, SQL*Plus will report the line and column number of the error in addition to the error message. Many APIs, on the other hand, will just report the PLS-00201 error by default.
SQL> declare
2 i integer;
3 begin
4 j := 1;
5 end;
6 /
j := 1;
*
ERROR at line 4:
ORA-06550: line 4, column 3:
PLS-00201: identifier 'J' must be declared
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored
Similarly, if you execute a SQL statement with an invalid variable name, SQL*Plus will get the column and line position and put a * under the offending character, i.e.
SQL> create table a( col1 number );
Table created.
SQL> insert into a( colN ) values ( 1 );
insert into a( colN ) values ( 1 )
*
ERROR at line 1:
ORA-00904: "COLN": invalid identifier
Most PL/SQL IDE's (TOAD, SQL Developer, etc.) will do something similar by interrogating the appropriate OCI APIs under the covers. Precisely how this is done, however, will depend on the API.
I don't know of any way to get Oracle to make the error more specific. Maybe some future version will improve this error message.
Instead of just staring at it, though, there are other things you can try. For example, convert each variable in the SQL statement to a literal one at a time, until the error goes away. If possible, generate the list of variable names instead of typing them manually.