EXECUTE IMMEDIATE with USING clause giving errors - stored-procedures

All,
I am very new to stored procedures in general but I am struggling especially with those in Oracle. I have created a very simple example of what I am trying to accomplish and I am still getting the same error with this simplified version.
The example stored procedure is as follows:
CREATE OR REPLACE PROCEDURE ashish_test
AUTHID CURRENT_USER IS
BEGIN
DECLARE
v_tab VARCHAR2(50);
v_strSQL VARCHAR2(50);
BEGIN
v_strSQL := 'SELECT * FROM :1';
v_tab := 'ex.emp';
EXECUTE IMMEDIATE v_strSQL USING v_tab;
END;
END;
When I call the above stored procedure using CALL ashish_test(), I get :
Error Message http://web1.twitpic.com/img/12831839-06a3ea536df5d5a0a839eb83d9e59d25.4a3936b8-scaled.jpg
Based on this article (Look for Example 7-1), USING keyword should replace the numbered placeholder (:1) within v_strSQL with the value stored in v_tab. However, I keep getting invalid table error. I am guessing it's because EXECUTE IMMEDIATE is unable to replace the placeholder with the value for some reason but I am not sure why that is. Does anyone know if I am doing something stupid here?
I am running this on Oracle 10g database & using PL/SQL Developer.

The USING clause is only for bind variables (i.e. where you would use column names in a select statement), not table names. Typical usage would look like this:
Select col1 from table1 where col2 = :a
If you want to use variable table names use something like this:
v_tab := 'ex.emp';
v_strSQL := 'SELECT * FROM ' || v_tab;
EXECUTE IMMEDIATE v_strSQL;

Related

Unable to retrieve multiple rows using cursor from database table using stored procedure DB2

I am trying to retrieve multiple rows from table using stored procedure and it doesn't work for me. My stored procedure is as follows,
CREATE OR REPLACE PROCEDURE E_Enquiry
(IN SourceQueue1 VARCHAR(30) ) LANGUAGE SQL
BEGIN
DECLARE C1 CURSOR FOR
select CreationTime
from ms.Exception_Message
where SourceQueue = SourceQueue1;
open c1;
END;
I am trying to call the stored procedure from Mule Anypoint Studio using the Database connector and have seen the result as null when I print the payload with a logger. If I try to modify the query as it returns a single row it works (without using cursor).
Please help to resolve this. Thanks.
What platform and version of DB2?
Try the adding
DYNAMIC RESULT SETS 1
WITH RETURN TO CLIENT
Like so:
CREATE OR REPLACE PROCEDURE E_Enquiry
(IN SourceQueue1 VARCHAR(30) )
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
DECLARE C1 CURSOR WITH RETURN TO CLIENT FOR
select CreationTime
from ms.Exception_Message
where SourceQueue = SourceQueue1;
open c1;
END;

passing arrays as parameters to plsql procedure

I need was playing around with sql developer and I have ran into a wall here...
I need to run a simple update query on a table and I want to pass in an array of Ids and update all the rows pointed by those Ids.
I have written the following stored procedure
PROCEDURE SAMPLE_PROCEDURE(SAMPLE_ARRAY IN NUM_ARRAY)
AS
BEGIN
UPDATE RETURNLIST_PICKLIST_MAPPING
SET PICKLIST_ID = 1111111
WHERE RETURNLIST_ID IN (SELECT * FROM TABLE(SAMPLE_ARRAY));
END SAMPLE_PROCEDURE;
NUM_ARRAY is a custom type defined as follows
create or replace
TYPE NUM_ARRAY
AS VARRAY(40) OF NUMBER(38, 0);
When I run the stored procedure in sql developer I want to input the value for SAMPLE_ARRAY. I have tried (2222,1111,1234) and [2222,1111,1234] and {2222,1111,1234} and each time I get "expression is of wrong type" error.
I desperate need help with this guys....
You did not show how did you assign values to your varray variable. But, I believe you can do it like this:
DECLARE
V_T NUM_ARRAY;
BEGIN
V_T := NUM_ARRAY(1,2,3);
SAMPLE_PROCEDURE(V_T);
END;
/
In general, you can define a standalone VARRAY as follows:
CREATE Or REPLACE TYPE varray_type_name AS VARRAY(n) OF <element_type>;
Or, within PL/SQL block:
TYPE varray_type_name IS VARRAY(n) of <element_type>
Refer to this for more details

How to define an Array of values (or a Column) into a Procedure Argument?

I am working on a Netezza SP and is stuck with a problem.
I have a SP, defined as say:
CREATE OR REPLACE PROCEDURE MY_PROC(VARCHAR(ANY)) RETURNS INTEGER LANGUAGE NZPLSQL
AS
BEGIN_PROC
DECLARE
v_temp ALIAS FOR $1;
/* Other decalarations */
result_ts INTEGER;
BEGIN
result_ts := 0;
/* Procedure Body */
RETURN result_ts;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Exception Raised: %', SQLERRM;
END;
END_PROC;
If I am running this SP with one value, such as:
SELECT MY_PROC('TEST_INPUT');
But if I am trying to run it with a column value, such as:
SELECT MY_PROC(TEST_COLUMN) FROM TEST_TABLE;
Its giving me error as:
ERROR: Can't use a stored procedure in this context
I know that in the second scenario I am passing an Array (i guess) but this is not what the Procedure has expected.
Now I am trying to have a procedure that can accept these kind of values but could not succeeded so far, LOOPing and all I have taken care but only problem is the Argument which I don't know how to pass.
Any help would be appreciated, let me know if I need to provide any extra info on this.
Asif
Stored procedures in Netezza, as of v7.2, can only be called in the following ways, as documented here.
CALL sproc_name(...);
EXEC sproc_name(...);
SELECT sproc_name(...);
Note that the SELECT form does not allow a FROM clause.
If you want the stored procedure to act on a particular column from a particular table that changes from invocation to invocation, you could pass the names of those as arguments to the stored procedure and have the entirety of the SQL logic encoded within. You could even pass arbitrary code into the stored procedure to build a query internally.
The way you are trying to call it now is more like calling a user defined function, and that simply won't work with stored procedures here.

Cursor not returned from Query

I'm using Delphi XE and FireBird 2.5.
Try use a TSQLStoredProc and give me the error "Cursor not returned from Query" when I put the Active property to TRUE.
An dummy example of storedproc
CREATE PROCEDURE NEW_PROCEDURE
RETURNS(
RDO SMALLINT)
AS
BEGIN
Rdo = 5;
/* Procedure body */
SUSPEND;
END;
As a workaround, a query like SELECT * FROM NEW_PROCEDURE should work (using TSQLQuery).
I think you are supposed to use the ExecProc method instead of Open / Active. Setting Active to true should only be used if your SQL Statement returns a ResultSet (a set of records), which yours doesn't.
Regards,
Stefaan

Delphi / ADO : how to get result of Execute()?

I have declared AdoConnection : TADOConnection; and successfully connected to the default "mysql" database (so, no need to pass that code).
Now, taking baby steps to learn, I would like to AdoConnection.Execute('SHOW DATABASES', cmdText); which seems to work ok, in the sense that it doesn't throw an exception, but I am such a n00b that I don't know how I can examine the result of the command :-/
Halp!
#mawg, the SHOW DATABASES command returns an dataset with one column called 'Database', so you can use the TADOQuery component to read the data.
try this code.
var
AdoQuery : TADOQuery;
begin
AdoQuery:=TADOQuery.Create(nil);
try
AdoQuery.Connection:=AdoConnection;
AdoQuery.SQL.Add('SHOW DATABASES');
AdoQuery.Open;
while not AdoQuery.eof do
begin
Writeln(AdoQuery.FieldByname('DataBase').AsString);
AdoQuery.Next;
end;
finally
AdoQuery.Free;
end;
end;
What you need is to reach the returned _Recordset.
If you don't mind using the Delphi components, you should use TADODataSet or TADOQuery to execute a SQL command which can return any results (or the more low-evel TADOCommands' Execute methods).
If you wanty something realy simple, w/o all the VCL balast, you mignt want to try the TADOWrap class from ExplainThat (MIT licenced).
You must use an TADOQuery connected to TADODataBase. At property SQL you must include the SQl statament to retrive databases in SGDB. In SQL Server you can do this:
SELECT * FROM sysdatabases
In MySQL must exist something similar to retrieve the names.
You can connect this TADOQuery to a TDataSource and a DBGrid to see visual result or use code to explore the result of the query (some similar to this):
ADOQuery1.Open;
while not ADOQuery1.eof do begin
Name := ADOQuery1.FieldByName('DBName').AsString;
ADOQuery1.Next;
end;
Regards
You need TAdoQuery to execute statements, that return results.
If you simply want to populate a grid why dont you use adotable ?
Adotable.open;
Adotable.first;
While NOT adotable.eof do(not sure about not or <>)
Begin
Put values in variant or array;
Adotable.next;
End
Then you can let any UI access the array or variant.
Or populate a dataset.

Resources