Accessing to OUT parameter (t_cursor type) from stored procedure using go and InstantClient - database

I'm dealing with an Oracle DB, connecting from go via InstantClient (version 11) (https://github.com/mattn/go-oci8). I need to be able to load this object and browse results... t_cursor output parameter.
I have tried many strategies, I know how to map function parameters to go structures but I don't know how to work with t_cursor type since it seems not being implemented in InstantClient
Example of stored procedure
create or replace procedure EXAMPLE(a IN NUMBER, b IN NUMBER, c OUT T_CURSOR) AS BEGIN
[Edit] We have also tried to execute SQL blocks from code to try to handle this third parameter.
i.e.
If you add something like
declare
c t_cursor;
begin
EXAMPLE(:1, :2, c)
end
then I don't know how you can get the block to return a result set that contains the cursor.
declare
c t_cursor;
begin
EXAMPLE(:1, :2, c)
select 1, c from dual
end
The whole block returning the result of that select would be ideal but oracle blocks do not return result sets afaik.
Anyone who can bear a hand on this?
Thank you very much

It can be done with the driver https://github.com/rana/ora instead.
*Rset may be passed to Stmt.Exe when prepared with a stored procedure accepting an OUT SYS_REFCURSOR
The README.me even has that exact example.
Caveats:
It's unclear whether the database/sql interface may be used or you are limited to the lib specific API.
Instant Client gets restricted to versions from 12.1.0.1.0 on.

Related

Procedure not running in toad asking for the variable

I'm using TOAD for Oracle. I'm trying to execute a stored procedure with two parameters - one IN and one OUT. It looks like this:
PROCEDURE get_stuff (
parm_1 IN VARCHAR2,
parm_2 OUT currefcursor)
In the SQL Editor window in TOAD, I've tried various things to no avail. I'm sure this is something simple that I'm missing, 'cause I've tried all sorts of things I've seen in other solutions here at Experts Exchange, but can't get past various errors. Here's what I think should work from what I've seen here:
var p1 VARCHAR2 := 'some text';
var p2 currefcursor;
EXEC get_stuff( :p1, :p2 );
When I run this, though, the SQL Editor pops up a window titled 'Variables' that appears to be looking for a value. No matter whether I put something in the 'Value' textbox or not, when I click OK, it says:
ORA-00900: invalid SQL statement
and highlights the 'var' in front of p1.
Please tell me what I'm missing!
Status Solved Priority Medium Security Public Views 21999
As the second parameter is OUT, you have to declare the variable which will accept that value. Here's how; I don't know what currefcursor type is - I guess you do.
declare
l_out currefcursor;
begin
get_stuff(:p1, l_out);
end;
/
A simple option to view the result would be this: put this code into the editor and run it as a script; the result will be displayed in the Script Output tab.
variable l_out currefcursor
exec get_stuff(:p1, :l_out);
print l_out
Or, you could even create a wrapper function which returns cursor, and then select from it:
create or replace function f_get_stuff(p1 in number)
return currefcursor
is
l_out currefcursor;
begin
get_stuff(p1, l_out);
return l_out;
end;
/
select f_get_stuff(:p1) from dual;
You can use Toad to execute without writing the execution harness yourself as well. Here is one method using the Schema Browser. Select your object and right-click > Execute.
You are presented with a dialog asking for your input parameters. Set your inputs and you can see the generated execution harness below. You can also use this generated code as an educational guide to see one method of writing the code yourself.
Click OK and your function/procedure is executed and results are shown.

Dynamic cursor PERVASIVE

I'm trying to create SP with dynamic cursor for obtain the result of any Select statement
CREATE PROCEDURE CursorTest (:query IN VARCHAR(5000)) ;
BEGIN
DECLARE :out VARCHAR;
DECLARE :dynamicCursor CURSOR FOR EXEC (:query);
OPEN dynamicCursor;
/* cursor loop */
Cursorloop:
LOOP
FETCH NEXT FROM `enter code here`Cursorloop INTO :out;
End LOOP;
CLOSE dynamicCursor;
END;
I have 2 problems on that, Declare the cursor with the dynamic query and output the result as a row.
Thanks in advance
Since this question is tagged pervasive I'm assuming you want to achieve this in PervasiveSQL.
I don't think what you are trying to do is possible there. The main reason for this is that - to my knowledge - P-SQL has no aggregate functions to combine arbitrary columns or rows into a string (like e.g. PostgreSQL's string_agg).
Secondly, P-SQL does not support querying by column number. The :query argument can be any statement (even an invalid one!), so you don't know how many columns it'll produce.
On a more essential note: what is it exactly that you want to achieve? This stored procedure looks to me like an overly complicated way of just executing :query, and having no means of handling the result. If logging or analysis is your goal, wouldn't you be better off by using an external, more flexible (scripting) language to deal with the result set? Admittedly SQL is a programming language, but it has its limitations.

Converting dbase do while to sql

I wrote a dBase procedure and I'm having a hard time converting it to a SQL Server stored procedure.
This is what I have for dbase:
CLOSE ALL
SELECT A
USE DDCS_OLD
SELECT B
USE CROSSELL
DO WHILE .NOT. EOF()
mLAT1 = IND_LAT
mLONG1 = IND_LONG
IF mLAT1 > 0 .AND. mLONG1 < 0
SELECT A
GOTO TOP
DO WHILE .NOT. EOF()
mLAT2 = LAT
mLONG2 = LONG
mPROP_CODE = PROP_CODE
mDISTANCE = 3963.0 * ACOS(SIN(mLAT1/57.2958) * SIN(mLAT2/57.2958) + COS(mLAT1/57.2958) * COS(mLAT2/57.2958) * COS(mLONG2/57.2958 - mLONG1/57.2958))
SELECT B
REPLACE &mPROP_CODE WITH mDISTANCE
SELECT A
SKIP
ENDDO
ENDIF
SELECT B
SKIP
END DO'
I have never written a stored procedure before so I'm not sure how to go about a do while loop while using the two tables ddcs_old and crossell.
That looks like a tremendously complicated calculation that I would consider moving out of the database and into the application that is using this data, if at all possible.
However, I'm guessing that what DO WHILE .NOT. EOF() does in dbase is basically read one row at a time from the table, until it reaches the end. In a SQL Stored Procedure you would achieve this with a cursor:
DECLARE crDDCS_Old CURSOR LOCAL FORWARD_ONLY FOR
SELECT LAT, LONG, PROP_CODE FROM ddcs_old
OPEN crDDCS_Old
FETCH NEXT FROM crDDCS_Old
WHILE ##FETCH_STATUS = 0
BEGIN
-- Do your calculations here
FETCH NEXT FROM crDDCS_Old
END
CLOSE crDDCS_Old
DEALLOCATE crDDCS_Old
As I said, I would strongly recommend reconsidering the best way of implementing this functionality, a direct conversion to a stored procedure is highly unlikely to be the best approach. Cursors are inefficient and, apparently, more lines of code than the dbase equivalent. You'd need in-depth knowledge of what it was doing in dbase and how that data is being used, to come up with the best alternative.
You don't use sql like DBase. If at all possible, you want to execute any operation using a set based operation that update all corresponding rows with a single update command -- I.e., you avoid loops based on a cursor 99.97% of the time. Also, without column definitions for your DBase tables (and hopefully corresponding columns for your SQL tables), I don't know how you expect to get any help as it is not really possible to figure out what your existing code does.
However it also looks a like you you are doing great circle calculations, beginning in Sql 2008, you can use the geography data type, which has build in functions for a number of geographic features, including great circle distances.
You really need to get a little understanding of how SQL works instead of asking for some magic and opaque answer -- the time will be well spent and when you get stuck, S/O is a good source for getting unstuck.
I know this is more of a comment, but it is too long for a comment.

ADO.Net and stored procedure output parameters

In Ado.net, the code is calling a stored procedure with input and output parameters.
I understand that if some of the input parameters are optional (have default values in the SP), the code doesn't need to define and send the parameters values unless needed to.
My question is:
Does the same apply to the optional output parameters? can the code ignore the optional (has a default value) SP output parameters?
I could have tested it myself but I don't have a working example right now, and I am short of time.
Thanks you.
Yes. If a parameter has a default value then it may be safely omitted, irrelevant of the parameter direction (INPUT or OUTPUT). The fact that the procedure is called from ADO.Net is entirely irrelevant. Eg:
create procedure usp_test
#a int = 1 output,
#b int = 2
as
begin
set #a = #b;
end
go
exec usp_test
Whether is safe to do from a business rules point of view (ie. ignoring an OUTPUT parameter returned value), is entirely up to the specifics of the procedure and your app.
EDIT: Turns out I was wrong here, but I'm going to leave my answer because the information on SqlParameter might be useful. Sorry for the inaccuracy though.
I don't believe so. You must send in an OUTPUT parameter and in ADO.NET this is accomplished by adding a SqlParameter with it's ParameterDirection property set to ParameterDirection.Output.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.direction.aspx
http://msdn.microsoft.com/en-us/library/system.data.parameterdirection.aspx

How to declare local variables in postgresql?

There is an almost identical, but not really answered question here.
I am migrating an application from MS SQL Server to PostgreSQL. In many places in code I use local variables so I would like to go for the change that requires less work, so could you please tell me which is the best way to translate the following code?
-- MS SQL Syntax: declare 2 variables, assign value and return the sum of the two
declare #One integer = 1
declare #Two integer = 2
select #One + #Two as SUM
this returns:
SUM
-----------
3
(1 row(s) affected)
I will use Postgresql 8.4 or even 9.0 if it contains significant fetaures that will simplify the translation.
Postgresql historically doesn't support procedural code at the command level - only within functions. However, in Postgresql 9, support has been added to execute an inline code block that effectively supports something like this, although the syntax is perhaps a bit odd, and there are many restrictions compared to what you can do with SQL Server. Notably, the inline code block can't return a result set, so can't be used for what you outline above.
In general, if you want to write some procedural code and have it return a result, you need to put it inside a function. For example:
CREATE OR REPLACE FUNCTION somefuncname() RETURNS int LANGUAGE plpgsql AS $$
DECLARE
one int;
two int;
BEGIN
one := 1;
two := 2;
RETURN one + two;
END
$$;
SELECT somefuncname();
The PostgreSQL wire protocol doesn't, as far as I know, allow for things like a command returning multiple result sets. So you can't simply map T-SQL batches or stored procedures to PostgreSQL functions.

Resources