Call Oracle stored procedure from PowerBI - oracle

I am using PowerBI (64b) with an Oracle 11g database.
When I try to connect to Oracle by stored procedure, I get an error, I don't know if I'm doing it right. please appreciate any help.
Observation: if there is a connection to the database, I can list the tables, etc.
I'm not calling the stored procedure correctly, what should I change? Thanks a lot,
procedure SPU_LISTAR_1(
FINI IN DATE,
FFIN IN DATE,
RS_CURSOR_LISTA IN OUT TYP_CURSOR)
AS
BEGIN
OPEN RS_CURSOR_LISTA FOR
SELECT IDPROCESO,CAMPO1
FROM TABLA1
WHERE FECHA BETWEEN FINI AND FFIN ;
END;
This is how I call this stored procedure from PowerBI:
DECLARE RS_CURSOR_LISTA SYS_REFCURSOR;
BEGIN
[STOREDPROCNAME]('01/01/2019','05/01/2019');
DBMS_SQL.RETURN_RESULT(RS_CURSOR_LISTA);
END;
And this is the error I get:
An error was encountered while trying to connect.
Details: "Oracle ORA-06550: line3, column1":
PLS-00201: Identifier 'SPU_LISTAR_1' must be declared
ORA-06550: PL / SQL: Statement ignored
pls-00302: Component 'RETURN_RESULT' must be declared
ORA-06550: PL / SQL: Statement Ignored

Related

In Oracle DB how to avoid decompiling of objects dependent on a DBLink?

There is a DBLink to a remote DB and a package MY_PACKAGE (in the local schema) indirectly depending on it through MY_VIEW.
When DBLink is not valid (for whatever reason, i.e. connection is lost or credentials are changed on the remote) then the package becomes invalid. But it would be great to have it working, because this package has other responsibilities aside from negotiating through this DBLink. And overall, I do not think it is a desirable situation to have the schema object validity depending on an unstable parts like network connection.
I found this situation in a legacy code (see MY_PACKAGE.doSomething()) and I am not sure even whether this is a correct design. Could you share your opinion on this?
What is the proper approach to keep the package in a VALID state even when some DBLinks are not available?
For example, would it be correct to use a dynamic cursor referencing MY_VIEW, which fails to open ONLY when DBLink is not OK (i.e. MY_PACKAGE.doSomethingAgain()). Of course maybe there is a more natural approach to this problem. I will be glad to hear all options that could be appropriate for safe usage of DBLinks in Oracle.
Code:
-- DBLink --------------------------------------------------------------
CREATE DATABASE LINK "MY_LINK"
CONNECT TO "MY_USER" IDENTIFIED BY VALUES ':1' USING 'WHATEVER';
------------------------------------------------------------------------
-- Synonym -------------------------------------------------------------
CREATE OR REPLACE EDITIONABLE SYNONYM "MY_SYNONYM"
FOR "MY_REMOTE_SCHEMA"."MY_REMOTE_VIEW"#"MY_LINK";
------------------------------------------------------------------------
-- View ----------------------------------------------------------------
CREATE OR REPLACE VIEW "MY_VIEW" AS
SELECT a,b,c FROM "MY_SYNONYM";
> Compiler Error
> ORA-02063: preceding 2 lines from MY_LINK
> ORA-01017: invalid username/password; logon denied
> [Oracle][ODBC SQL Server Wire Protocol driver][SQL Server]
> Login failed for user 'MY_USER'. {28000,NativeErr = 18456}
------------------------------------------------------------------------
.
-- Package body --------------------------------------------------------
CREATE OR REPLACE PACKAGE BODY MY_PACKAGE AS
PROCEDURE doSomething()
IS
i NUMBER := 0;
BEGIN
FOR rec IN (SELECT * FROM "MY_VIEW")
LOOP
i := i + 1;
END LOOP;
END;
PROCEDURE doSomethingAgain()
IS
i NUMBER := 0;
my_cur SYS_REFCURSOR;
BEGIN
OPEN my_cur FOR 'SELECT * FROM MY_VIEW';
LOOP
FETCH my_cur -- ...
-- etc ...
i := i + 1;
END LOOP;
END;
END MY_PACKAGE;
> Compiler Error
> 7/4 PL/SQL: SQL Statement ignored
> 7/35 PL/SQL: ORA-04063: view "MY_VIEW" has errors
------------------------------------------------------------------------
The best option you have is to keep database links alive and kicking, I presume.
Another option is to move procedures - that use those suspicious database links - out of that package and make them either standalone stored procedures so that if they become invalid, only they are invalid (and not the whole package), or - possibly - put those procedures (that share the same destiny) into a separate package.
Yet another option is to use dynamic SQL because Oracle doesn't care whether any objects involved are valid or not until you actually try to use them. Something like this:
SQL> create database link my_link
2 connect to whoever
3 identified by whatever
4 using 'database_that_does_not_exist';
Database link created.
SQL> create or replace view my_view as
2 select * from some_table#my_link;
select * from some_table#my_link
*
ERROR at line 2:
ORA-12154: TNS:could not resolve the connect identifier specified
SQL> create or replace procedure my_proc as
2 l_id number;
3 begin
4 select id into l_id
5 from my_view;
6 end;
7 /
Warning: Procedure created with compilation errors.
SQL> show err
Errors for PROCEDURE MY_PROC:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/3 PL/SQL: SQL Statement ignored
5/8 PL/SQL: ORA-00942: table or view does not exist
But, with dynamic SQL:
SQL> create or replace procedure my_proc as
2 l_id number;
3 begin
4 execute immediate 'select id from my_view' into l_id;
5 end;
6 /
Procedure created.
SQL>
Looks OK, but not for long:
SQL> exec my_proc;
BEGIN my_proc; END;
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SCOTT.MY_PROC", line 4
ORA-06512: at line 1
SQL>
Yes, I know - not all code is simple enough to put it into dynamic SQL. Bigger it is, worse problems you have to maintain it, so that's just possibility I wouldn't really want to use.

Error while executing a stored procedure to drop a table

Getting error while executing a stored procedure that drops a table.
I have compiled the procedure successfully (used dynamic SQL for the code).
Tool used is SQL Developer.
CREATE OR REPLACE PROCEDURE sp_DROP(P_VAR IN VARCHAR2)
IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE'||P_VAR; -- passing table via parameter
END;
but I'm getting error while executing this procedure:
EXECUTE sp_DROP('CON1'); -- i have made sure CON1 is a legit table.
Error :
ORA-00950: invalid DROP option
ORA-06512: at "HR.SP_DROP", line 4
ORA-06512: at line 3
00950. 00000 - "invalid DROP option"
*Cause:
*Action:
Thanks for the help.
Add a space to the end of drop table.
CREATE OR REPLACE PROCEDURE sp_DROP(P_VAR IN VARCHAR2)
IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE '||P_VAR; -- passing table via parameter
END;

Creating a DB link if not created inside a stored procedure

I'm trying to code a stored procedure in Oracle. I don't have a ton of experience with it and I'm running to an issue. The end goal of the procedure is to take data from one DB and put it into another in a different form. I have most of the procedure working it seems but I'm having issues with something that seems like it should be simple. At the beginning of the code, I would like to check to make sure a DB link is created. If not, then I want to create the db link.
This is what I put inside my procedure:
IF (select count(1) from ALL_DB_LINKS where db_link = 'DB_LINK.NAME.COM') = 0 THEN
CREATE DATABASE LINK LINK_NAME
CONNECT TO username IDENTIFIED BY password
USING 'SID';
END IF;
I know the link works because I've done it outside this and did a lookup with it. The error I get when I try to compile is this:
Encountered the symbol "CREATE" when expecting one of the following:
I've done all the googling I think I can do and I cannot figure out what I am doing wrong. To head off the other question I have, I've also tried to do it by putting in:
DECLARE test_count number;
select count(1) into test_count from ALL_DB_LINKS where db_link = 'DB_LINK.NAME.COM';
BEGIN
IF test_count = 0 THEN
CREATE DATABASE LINK LINK_NAME
CONNECT TO username IDENTIFIED BY password
USING 'SID';
END IF;
END;
But I get the same error. I'm also not sure if having a begin inside a begin will work. Any help would be a great... well, help.
Oracle compiles packages and in order to do that all objects referenced in code need to already exist. This includes objects referenced over a database link. Things will get marked invalid if the referenced objects don't exist. Usually a DBA will create and maintain such an environment using PL/SQL scripts and not stored procedures.
If you really want to anyway:
EXECUTE IMMEDIATE q'[ CREATE DATABASE LINK LINK_NAME
CONNECT TO username IDENTIFIED BY password
USING 'SID']';
If you really need to do this, you can create the link using dynamic SQL as Ed Gibbs suggested and Brian showed, as long as the link already exists at the point the procedure is created:
create database link test_link
connect to scott identified by oracle
using 'ORCL';
Database link created.
create or replace procedure p42 as
l_count number;
l_dummy dual.dummy%type;
begin
select count(*) into l_count
from all_db_links
where db_link = 'TEST_LINK';
if l_count = 0 then
execute immediate q'[
create database link test_link
connect to scott identified by oracle
using 'ORCL'
]';
end if;
select dummy into l_dummy from dual#test_link;
dbms_output.put_line('Value from remote database: ' || l_dummy);
end;
/
Procedure created.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
But the procedure won't compile if the link doesn't already exist:
drop database link test_link;
create or replace procedure p42 as
...
end;
/
Warning: Procedure created with compilation errors.
show errors
Errors for PROCEDURE P42:
LINE/COL ERROR
-------- -----------------------------------------------------------------
16/5 PL/SQL: SQL Statement ignored
16/5 PL/SQL: ORA-00942: table or view does not exist
Curiously it doesn't object if you create the procedure while the link exists, and then drop the link; the procedure stays valid, the dynamic SQL works to recreate the link, and the procedure runs successfully:
drop database link test_link;
Database link dropped.
select object_type, object_name, status from all_objects
where object_type = 'PROCEDURE' and object_name = 'P42';
OBJECT_TYPE OBJECT_NAME STATUS
--------------- --------------- ---------------------
PROCEDURE P42 VALID
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
I would have expected dropping the link to invalidate the procedure, but apparently not, despite it appearing in all_dependencies. You can't recompile the procedure though:
drop database link test_link;
Database link dropped.
alter procedure p42 compile;
Warning: Procedure altered with compilation errors.
show errors
Errors for PROCEDURE P42:
LINE/COL ERROR
-------- -----------------------------------------------------------------
16/5 PL/SQL: SQL Statement ignored
16/5 PL/SQL: ORA-00942: table or view does not exist
In order to let you compile (or recompile) while the link does not exist, you'd need to reference the link using dynamic SQL as well:
drop database link test_link;
drop database link test_link
*
ERROR at line 1:
ORA-02024: database link not found
create or replace procedure p42 as
....
execute immediate 'select dummy from dual#test_link' into l_dummy;
dbms_output.put_line('Value from remote database: ' || l_dummy);
end;
/
Procedure created.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
drop database link test_link;
Database link dropped.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
drop database link test_link;
Database link dropped.
alter procedure p42 compile;
Procedure altered.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.

Why can't execute SCHEMA_NAME.PACKAGE_NAME.PROCEDURE, Oracle

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;

Including the schema name when calling a PL/SQL procedure doesn't work in one schema but does in another

This problem came up when trying out the Unit Testing capabilities of SQLDeveloper.
When running a test for a procedure that is created within my schema I am seeing an error however when the same procedure is run in one of the oracle supplied schemas it works without an issue.
SQL Developer generates the following calls:
1) This one doesn't work (error is shown below):
BEGIN
"IANC"."SIMPLE_PARAMETER"(P_X => 123);
END;
2) This one does:
BEGIN
"HR"."SIMPLE_PARAMETER"(P_X => 123);
END;
This is the procedure:
CREATE OR REPLACE PROCEDURE SIMPLE_PARAMETER
(
P_X IN NUMBER
)
IS
BEGIN
null;
END SIMPLE_PARAMETER;
The following is the output from SQLPLUS, where you can see when the procedure is run in my schema I see an error whilst when running the same procedure in another schema the procedure works as expected:
In case of need my I am using Oracle Enterprise Edition 11.2.0.1.0
Update
Screen shot showing procedure signatures
I should also mention that if I remove the schema name from the procedure call then the procedure runs and completes as expected.
Thanks in advance for any help received.
Are you sure that the SIMPLE_PARAMETER procedure in IANC is the same (or at least has the same signature) as the one in HR? What do you get from `DESCRIBE "IANC"."SIMPLE_PARAMETER".
(P.S. since your identifiers are all upper-case, you shouldn't need the double quotes at all.)
Added: Another possibility is that you have a package called IANC in the IANC schema, so Oracle is looking for a procedure in that package called SIMPLE_PARAMETER that does not exist. Example:
SQL> exec bigdecimaltest
PL/SQL procedure successfully completed.
SQL> exec dcosta.bigdecimaltest
PL/SQL procedure successfully completed.
SQL> create or replace package dcosta as
2 end;
3 /
Package created.
SQL> exec dcosta.bigdecimaltest
BEGIN dcosta.bigdecimaltest; END;
*
ERROR at line 1:
ORA-06550: line 1, column 14:
PLS-00302: component 'BIGDECIMALTEST' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
This seems like buggy behavior -- if the attempt to resolve the name as package.member doesn't succeed, I think Oracle ought to then try it as schema.object, but it looks like once it has found a match on the package name it won't reconsider that.

Resources