I have got a package which contains a cursor, a table type on that cursor and a function that returns the table.
create or replace package RAPI is
cursor coordAndImgCursor is select latitude, longitude, picture from rapi_buildings;
type coordAndImgTable is table of coordAndImgCursor%rowtype;
function retreiveCoordsAndImgs(
latitude in number,
longitude in number,
area in number)
return coordAndImgTable;
end RAPI;
/
Now I am trying to get this table into a Java array, so I need to create a procedure that has an OUT parameter.
create or replace procedure jdbc_return(
latitude IN number,
longitude IN number,
area IN number,
return_table OUT RAPI.coordAndImgTable)
as
begin
return_table := RAPI.retreiveCoordsAndImgs(latitude, longitude, area);
end jdbc_return;
/
The code is correct and works fine.
Now I have the following Java code:
String jdbc_return = "BEGIN
jdbc_return(47.176885, 27.576675, 0.001, ?);
END;";
CallableStatement cstmt = conn.prepareCall(jdbc_return);
cstmt.registerOutParameter(1, OracleTypes.CURSOR);
cstmt.execute();
but I receive this error:
PLS-00306: wrong number or types of arguments in call to 'JDBC_RETURN'
ORA-06550: line 1, column 7:
How can I get that table from Oracle?
Related
I can't get Flyway 7.7.3 to parse the HyperSQL CREATE PROCEDURE statement below. Though it used to work I guess, with an older version, as this is a 2018 script that I'm trying to resurrect.
CREATE PROCEDURE proc_findByLastname(IN name VARCHAR(30)) READS SQL DATA
DYNAMIC RESULT SETS 1
BEGIN ATOMIC
DECLARE persons_by_lastname_cursor CURSOR FOR
SELECT * FROM persons WHERE last_name = name;
OPEN persons_by_lastname_cursor;
END;
I unsuccessfully tried to inline the different lines, to get rid of the "DYNAMIC RESULT SETS 1" line, and couldn't understand what I read from inside the parser in step-by-step debug mode neither.
This is the complete trace :
Caused by: org.flywaydb.core.api.FlywayException: Unable to parse statement in db/migration/V2__procedure.sql at line 1 col 1. See https://flywaydb.org/documentation/knownparserlimitations for more information: Incomplete statement at line 1 col 1...
The referred limitations doesn't seem to apply: I tried to change the variable's name.
I also tried to change the delimiter, still no luck!
DELIMITER /;
CREATE PROCEDURE proc_findByLastname(IN lastname VARCHAR(30)) READS SQL DATA
DYNAMIC RESULT SETS 1
BEGIN ATOMIC
DECLARE persons_by_lastname_cursor CURSOR FOR
SELECT * FROM persons WHERE last_name = lastname;
OPEN persons_by_lastname_cursor;
END/;
Problem statement: we want to restrict the direct access to all the external STAGES to all the USER'S or DEVELOPER'S. We wanted these STAGES to be accessed through stored procedure or table UDF using LIST command.
We have following two working solutions :
Solution 1
Write a stored procedure and return a list command result set as single array or varchar with column delimiter (i.e. | ) and record delimiter (i.e. new line character)
Run view after calling above stored procedure using RESULT_SCAN(), LAST_QUERY_ID() and LATERAL SPLIT_TO_TABLE() functions to show the result as flattened row level output similar to original LIST command.
LIMITATIONS
As the view is using LAST_QUERY_ID and RESULT_SCAN functions its mandatory to call the SP before the select on view every time otherwise select on view will fail.
Solution 2
Write a stored procedure and create volatile table inside it to store the list command result.
Run the select query on the volatile table created from the above stored procedure.
Both above solutions are working fine for us but with stored procedure approach the result can't be seen as tabular format with a single call to the stored procedure. As snowflake doesn't supports PL/SQL function like "dbms_output.put_line()" .
It's always a 2-step solution.
Call stored procedure
View result from that stored procedure output using RESULT_SCAN(), LAST_QUERY_ID() functions or creating table inside the stored procedure and run query on the created table after stored procedure execution is complete.
Expected solution
We want to view the output of a stored procedure or UDF in a single call with similar representation like any other query output in Snowflake Web UI worksheets.
We want to know if there is any possibility to use LIST command in snowflake UDF or UDTF any LANGUAGE like SQL or JAVASCRIPT will work for us.
Or else if we can call a stored procedure (i.e. explained in above two solutions) inside a UDF this will also suffice our need.
Please let us know if there is any possible solution for the any of the above expected output.
I did not completely understand the requirement, but are you trying to do something like below
CREATE OR REPLACE PROCEDURE LIST_EXTERNAL_STAGE(stage_name varchar)
RETURNS VARIANT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var return_stage_rows = [];
var snowstmt = snowflake.createStatement({
sqlText: 'LIST '+ STAGE_NAME
});
var query_result = snowstmt.execute();
var end_of_table = snowstmt.getRowCount();
var counter = 0;
while (counter <= end_of_table) {
query_result.next();
return_stage_rows.push(query_result.getColumnValue(1),query_result.getColumnValue(2),query_result.getColumnValue(3),query_result.getColumnValue(4))
counter += 1;
}
return return_stage_rows;
$$;
call LIST_EXTERNAL_STAGE('#EMPLOYEE_STAGE');
I try to return a few values from a stored procedure without using reftable in Netezza.
CREATE OR REPLACE PROCEDURE TMP_GETTABLEINFO(CHAR(any), VARCHAR(any), VARCHAR(any))
returns char(1), varchar(30)
EXECUTE AS OWNER
LANGUAGE NZPLSQL
AS
begin_proc
DECLARE
a ALIAS FOR $1;
b ALIAS FOR $2;
BEGIN
...
RETURN a, b;
END;
Is it possible?
How?
My results are: ERROR [HY000] ERROR: Must specify LANGUAGE
I don't think this is possible. I haven't seen a case with multiple values being returned.
From the documentation (Netezza_stored_procedures_guide.pdf): Typically, an NZPLSQL procedure returns a unique return value, but it can also return a result set in the form of a specified table.
To create a stored procedure that returns a result set:
Define the stored procedure with a return value of RETURNS REFTABLE (<table-name>) to indicate that it returns a result set that looks like the specified table.
Inside the body of the procedure, use the variable REFTABLENAME to refer to the results table.
Hi I want to post calc field(cemi) to table (sql). when I calc all field the last field doesn't post on sql table. because last field (cemi) type fkcalc how can I post fkcalc type field to sql table Thanks in advance!
procedure TForm1.ADOQuery1CalcFields(DataSet: TDataSet);
begin
ADOQuery1.FieldValues['cemi']:=
((ADOQuery1.FieldValues['boyuk1'] + ADOQuery1.FieldValues['boyuk2'] +
ADOQuery1.FieldValues['boyuk3'])*0.35)+((ADOQuery1.FieldValues['kicik1'] +
ADOQuery1.FieldValues['kicik2'])*0.25) +(ADOQuery1.FieldValues['qara1']*0.30);
end;
I'm not quite sure what you mean by
the last field doesn't post on sql table
If the "last field" you are referring to is your "Cemi" one and that is a column which is in the table on your SQL Server, it will not get posted back there if you have defined it as a calculated field in your AdoQuery1 in the Object Inspector. Fields with a FieldKind of fkCalculated are local to the AdoQuery.
Just assigning a value to the calculated field is sufficient to "post" it locally to the AdoQuery, as I imagine you know. What you want to do to debug your problem (because readers like me cannot debug it fr you) is to more easily see what value, if any, is being assigned to it.
From that point of view, your code is suffering from "premature optimisation" which will make it difficult for you to see what is going wrong. Try this instead:
In your ADOQuery1CalcFields, declare a local variable for each of the fields you are accessing, including the calculated one. Choose the variable types to suit the fields:
var
Boyuk1 : Double; // or Integer, etc
[...]
Cemi : Double;
Assign values to the local variables, using the AsXXXX (type) of the fields:
Cemi := 0;
if not AdoQuery1.FieldByName('Boyuk1').IsNull then
Cemi := Cemi + AdoQuery1.FieldByName('Boyuk1').AsFloat;
[etc]
That way, at least you'll be able to see the point at which the calculation goes wrong (if it does).
I've used FieldByName().AsFloat, rather than FieldValues[], because FieldValues[] is a Variant, which can be Null, and you don't want that when you are assigning values to it which mat themselves be variants.
Also
Check that AutoCalcFields is set to True for AdoQuery1.
Put a debugger breakpoint on the first line of ADOQuery1CalcFields. Compile and run and check that the breakpoint hits - if it doesn't, there's your answer. Single-step the debugger through each line of the procedure, and, after the final line, use Ctrl-F7 to evaluate the value of AdoQuery1.FieldByName('Cemi').AsFloat.
I'm selecting an email address but I don't want to display the full email. Only the part before the '#'. How can I cut it. I know how to display only certain amount of characters or numbers. But how do I specify to display only till the '#' symbol.
Thank you.
Recent versions of Informix SQL have the CHARINDEX() function which can be used to isolate where the '#' symbol appears:
SELECT LEFT(email_addr, CHARINDEX('#', email_addr)-1)
CHARINDEX() will return 0 if not found, otherwise the ordinal position of the located string. My testing found that LEFT() doesn't complain about being passed 0 or -1, so it's safe to execute this as is, you don't have to verify that you get something back from CHARINDEX() first.
CREATE TEMP TABLE ex1
(
email_addr VARCHAR(60)
) WITH NO LOG;
INSERT INTO ex1 VALUES ('ret#example.com.au');
INSERT INTO ex1 VALUES ('emdee#gmail.com');
INSERT INTO ex1 VALUES ('unknown');
INSERT INTO ex1 VALUES (NULL);
INSERT INTO ex1 VALUES ('#bademail');
SELECT LEFT(email_addr, CHARINDEX('#', email_addr)-1) FROM ex1
... produces:
(expression)
ret
emdee
5 row(s) retrieved.
If you have an older version of Informix that doesn't support CHARINDEX(), you'll be forced to iterate through the string character by character, until you find the '#' symbol.