PostGIS in PLSQL; Properly defining function; resolving conflicting or redundant options - plsql

As you can figure from the code below, I am new to PLSQL. I try to allocate a point to a polygon, but only upon a function call. To this end I wanted to use PostGIS. However, I fail in generating the function in general. Could someone be so kind and explain the construction of such a function for replication purposes?
I jsut want to return the resulting view
CREATE OR REPLACE FUNCTION public.point_polygon_allocation(user_id)
RETURNS var_view
AS
$$
DECLARE
var_view VIEW;
BEGIN
RETURNS SELECT * INTO var_view
FROM polygon_relation AS poly
INNER JOIN user_table AS loc ON ST_Contains(poly."polygon", loc."location")
WHERE user_table.id = user_id;
RETURN var_view;
END;
$$
;

I actually came to a solution. First of all, I noticed that I used PlPgSQL and not PlSQL.
Regarding the solution, it turned out considerably shorter than I imagined:
CREATE OR REPLACE FUNCTION public.point_polygon_allocation(lat numeric, lon numeric)
RETURNS TABLE (
id int,
polygon_id int
)
AS
$$
DECLARE
lat numeric;
lon numeric;
BEGIN
RETURN QUERY
SELECT poly.id, poly.polygon_id
FROM polygon_relation AS poly
WHERE ST_Contains(poly."polygon", ST_MakePoint(lat,lon));
END;
$$
LANGUAGE plpgsql;
SELECT *
FROM point_polygon_allocation(52.520008, 13.404954);

Related

A cursor in a function - MariaDB

I have a task to use cursor to write a function that receives a movie title and then returns pay of actors involved in this movie.
I wrote something like this:
DELIMITER $$
CREATE FUNCTION getPay(movieTitle varchar(90))
RETURNS int;
BEGIN
DECLARE P int;
DECLARE done int DEFAULT FALSE;
DECLARE payCursor CURSOR FOR
(SELECT A.pay FROM actors A JOIN movie M ON M.id=A.movie WHERE M.title=movieTitle);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN payCursor;
loop_read : LOOP
FETCH payCursor INTO P;
IF done THEN
LEAVE loop_read;
END IF;
RETURN P;
END LOOP;
CLOSE payCursor;
END $$
DELIMITER ;
It's not a secret it's not working. I don't know how to return a set, moreover as I've read it's not possible in MariaDB. I tried to create temporary table but it's not good solution if you want to use this function several times. Also I would like to use this function in another task where I have to write a procedure to pay all the actors. I'm not sure I got the idea of cursors.
That function seems to be getting one (any one) row from the query. This would replace the function:
SELECT A.pay
FROM actors A
JOIN movie M ON M.id=A.movie
WHERE M.title=movieTitle)
LIMIT 1;
Or, since it is a function, get rid of the cursor, and have only that in the function.

expression is of wrong type for function

CREATE OR REPLACE FUNCTION k_w_b_salary(k IN NUMBER, b IN BOOLEAN)
RETURN EMP.ENAME%TYPE IS
names name_table;
BEGIN
IF (b = true) THEN
SELECT ENAME BULK COLLECT INTO names
FROM
(SELECT *
FROM EMP
ORDER BY SAL ASC)
WHERE ROWNUM <= k;
RETURN names;
ELSIF (b = false) THEN
SELECT ENAME BULK COLLECT INTO names
FROM
(SELECT *
FROM EMP
ORDER BY SAL DESC)
WHERE ROWNUM <= k;
RETURN names;
END IF;
END;
And I get this error:
12/9 PL/SQL: Statement ignored
12/16 PLS-00382: expression is of wrong type
20/9 PL/SQL: Statement ignored
20/16 PLS-00382: expression is of wrong type
I have this function that tries to find the best/worst paid employees. But i get the above error.
I think it's something to do with the ROWNUM but I am not sure.
I think the lines the error points out are not the lines with the error.
I had this function writen differently and the lines in the error where pointing to the ROWNUM <= k lines.
I have tried putting a fixed number there (<= 3) for example and I got the same error.
I have no idea what else to try, i can't really understand why this is not working.
It's not obvious to me why this is not working. I think it should work fine but obviously it dousen't.
The code for the table i use is :
CREATE OR REPLACE TYPE name_table IS TABLE OF VARCHAR2(10);
Any help is appreciated!
In the function declaration, you said
RETURN EMP.ENAME%TYPE
I assume the data type of column ENAME in table EMP is some sort of string (VARCHAR2(40) or similar) - right?
In the declarations section, you declare a variable names of data type name_table. You didn't show us the definition of the name_table type (that must be given outside the function, not in it); we can probably assume it is a nested table of some sort. Right? [EDIT - I take that back; you did show us your definition of name_table, at the end of your question.]
In the end, your function returns names. Which is of type name_table. But you said the function returns something else: EMP.ENAME%TYPE. In particular, you said the function returns a scalar data type, but you are returning a collection.
This will not work even if the collection has a single element. A table with a single "record" is not the same data type as the "record" itself - even if an actual table has a single "record" in it.
(And, much more so, when the table has three records in it!)
Rather: It seems that you want a table function: one that returns a table of things. If so, then declare the function that way. Perhaps you want the function to
RETURN NAME_TABLE
(at the top, in the function declaration)

mariadb user defined aggregate function

I am using mariadb 10.3.9, and have created a user defined aggregate function (UDAF) and placed in a common_schema. This schema contains my utility functions to be used by other schema/databases on the same server.
The issue is that when calling the UDAF while using any other schema, it always return NULL!
The following is to demonstrate the issue:
CREATE SCHEMA IF NOT EXISTS common_schema;
DELIMITER $$
DROP FUNCTION IF EXISTS common_schema.add_ints $$
CREATE FUNCTION common_schema.add_ints(int_1 INT, int_2 INT) RETURNS INT NO SQL
BEGIN
RETURN int_1 + int_2;
END $$
DROP FUNCTION IF EXISTS common_schema.sum_ints $$
CREATE AGGREGATE FUNCTION common_schema.sum_ints(int_val INT) RETURNS INT
BEGIN
DECLARE result INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN result;
LOOP FETCH GROUP NEXT ROW;
SET result = common_schema.add_ints(result, int_val);
END LOOP;
END $$
DELIMITER ;
Now, calling it this way, returns the result as expected:
USE common_schema;
SELECT common_schema.sum_ints(seq)
FROM (SELECT 1 seq UNION ALL SELECT 2) t;
-- result: 3
Calling it using any other schema, it returns NULL:
USE other_schema;
SELECT common_schema.sum_ints(seq)
FROM (SELECT 1 seq UNION ALL SELECT 2) t;
-- result: null
Am I missing something here? Is there any configuration that is missing?
Appreciate your help.
Reported as a Bug https://jira.mariadb.org/browse/MDEV-18100.
As a workaround, create the UDAF in every schema.

how to return a cursor or a result set from a oracle stored function

I have a stored function
CREATE OR REPLACE FUNCTION schedule(name in varchar2,pass in varchar2 )
begin
select t.name,s.starttime from traininfo t,schedule s, trainslot ts
where t.trainid in( select ts.trainid from trainslot
where ts.slotid in (select s.slotid from schedule s
where s.source='dhaka'
and s.dest='bogra' ))
end
I want to return this result set using a cursor.
I don't see where you are using either of the input parameters in your function. I'll assume that is either intentional or an oversight because you're simplifying the code. It also appears that your query is missing conditions to join between the traininfo, schedule, and trainslot tables in the outer query. It seems odd that your nested IN statements are turning around and querying the schedule and trainslot tables given this lack of join conditions. I don't know whether this is a result of copy-and-paste errors or something that was missed in posting the question or whether these are real problems. I'll make a guess at the query you're intending to write but if my guess is wrong, you'll have to tell us what your query is supposed to do (posting sample data and expected outputs would be exceptionally helpful for this).
CREATE OR REPLACE FUNCTION schedule(name in varchar2,pass in varchar2 )
RETURN sys_refcursor
is
l_rc sys_refcursor;
begin
open l_rc
for select t.name, s.starttime
from traininfo t,
schedule s,
trainslot ts
where t.trainid = ts.trainid
and s.slotid = ts.slotid
and s.source = 'dhaka'
and s.dest = 'borga';
return l_rc;
end;

Retrieve Database Constants

I want to retrieve database constants through query in front end to fill this constant string in DropDownList.
I have tried following query
select pr_Package.constant_String from dual;
Suggestions are welcome.
You can't reference a packaged constant directly in a SQL statement.
You can add a function to your package that returns the constant and call that function from SQL. Something like this will work (though you may want to consider moving the constant to the package body rather than the package specification once you have a function to return the data).
create or replace package pkg_const
as
some_constant number;
function get_constant
return number;
end;
create or replace package body pkg_const
as
function get_constant
return number
is
begin
return some_constant;
end;
end;
select pkg_const.get_constant from dual;

Resources