i have total of 4 records in my table
id | url | name | description | last_update
----+------------------------------------+---------------------+-------------+-------------
1 | https://www.postgresqltutorial.com | PostgreSQL Tutorial | |
2 | http://www.oreilly.com | O'Reilly Media | |
3 | https://www.google.com | Google | | 2013-06-01
4 | http://www.postgresql.org | PostgreSQL | |
i have written a function to delete by passing name as a parameter, now i want to pass multiple names but i am facing error.
CREATE OR REPLACE FUNCTION testing(first_name varchar(255))
RETURNS INTEGER AS
$BODY$
DECLARE emp_id INTEGER;
BEGIN
SELECT id into emp_id from links e where name = first_name;
DELETE FROM links WHERE id = emp_id;
return emp_id;
END
$BODY$
LANGUAGE plpgsql;
select * from testing('Google, PostgreSQL');
Error:- no function matches the given name and argument types. you might need to add explicit type casts
Since you have a comma separated list, you can cast your parameter as an array with string_to_array function then apply the any operator. Further there is no reason for pgplsql, this can be written in a single sql statement, then wrapped it into a sql parameter/function. (see demo)
create or replace procedure testing(first_names varchar(255))
language sql
as $$
delete from links
where name = any(string_to_array(first_names, ','));
$$;
If you want to pass several values, you have to define the function to accept several values. There are two ways:
a variadic function:
CREATE FUNCTION testing(VARIADIC first_name text[]) ...
This is called like
SELECT testing('arg1', 'arg2', 'arg3');
a function that accepts an array as parameter:
CREATE FUNCTION testing(first_name text[]) ...
This is called like
SELECT testing(ARRAY['arg1', 'arg2', 'arg3']);
Related
I was reading online about function on PostgreSQL and returns results
In this links:
SQL function return-type: TABLE vs SETOF records
How do I reference named parameters in Postgres sql functions?
http://www.postgresqltutorial.com/plpgsql-function-returns-a-table/
I have written this Function:
create or replace function brand_hierarchy(account_value int)
RETURNS table (topID INTEGER, accountId INTEGER, liveRowCount bigint,archiveRowCount bigint)
AS
$BODY$
SELECT * FROM my_client_numbers
where accountId = coalesce($1,accountId);
$BODY$
LANGUAGE sql;
Which works and return the results in a single column Type of record.
Note that might more than one row will return.
Now the response is:
record
(1172,1172,1011,0)
(1172,1412,10,40)
.....
I would like to get my results not as a record but as multiple columns
|---------|---------|------------|----------------|
| topID |accountId|liveRowCount|archiveRowCount |
|---------|---------|------------|----------------|
| 1172 |1172 | 1011 | 0 |
| 1172 |1412 | 10 | 40 |
Is there a way to return multiple columns from a PostgreSQL function
Functions returning a table (or setof) should be used in the FROM clause:
select *
from brand_hierarchy(1234)
I was able to see it as expected with this query:
SELECT * FROM brand_hierarchy (id)
I found this function crosstab I think it is what you're looking for
https://www.postgresql.org/docs/9.3/tablefunc.html
If I create a function f that queries a function I think it becomes easier to read if the return type is the name of a table instead of RETURNS TABLE(id integer, name text).
CREATE TABLE users ( id integer, name text );
CREATE OR REPLACE FUNCTION f()
RETURNS users
AS $$
SELECT * FROM users
WHERE FALSE
$$
LANGUAGE SQL;
But I'm getting weird results when the query in the function is returning zero rows.
SELECT * FROM f();
Expected result
+------+--------+
| id | name |
|------+--------|
+------+--------+
Actual result
+--------+--------+
| id | name |
|--------+--------|
| <null> | <null> |
+--------+--------+
If there are more columns they will still all be null. If the query in the function returns any rows then it works as expected. I'm not getting this behaviour if I'm using the RETURNS TABLE(...) syntax.
Is there a way to get around this?
I'm using PostgreSQL 9.6
That has nothing to do with the return type, but with the fact that you declared the function as returning a single row.
Replace
RETURNS users
with
RETURNS SETOF users
and your function will work as expected.
As your function is, it will return NULLs if the query has no results, and it will return the first row if the query has more than one result rows.
I need to fetch all records where these (5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5) values exists in categories_id column.
The value that I need to search in categories_id can be multiple because it coming from the form.
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | alias | description | categories_id |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 5565c08d-9f18-4b76-9cae-4a8261af48f5 | Honeycolony | honeycolony | null | ["5565bffd-7f64-494c-8950-4bef61af48f5"] |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| c8f16660-32cf-11e6-b73c-1924f891ba4d | LOFT | loft | null | ["5565bffd-25bc-4b09-8a83-4bef61af48f5","5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"] |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 5565c17f-80d8-4390-aadf-4a8061af48f5 | Fawn Shoppe | fawn-shoppe | null | ["5565bffd-25bc-4b09-8a83-4bef61af48f5","5565bffd-0744-4740-81f5-4bef61af48f5","5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"] |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
I have this function which work as in_array function php.
CREATE OR REPLACE FUNCTION public.arraycontain(
x json,
y json)
RETURNS boolean
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
DECLARE a text;b text;
BEGIN
FOR a IN SELECT json_array_elements_text($1)
LOOP
FOR b IN SELECT json_array_elements_text($2)
LOOP
IF a = b THEN
RETURN TRUE;
END IF;
END LOOP;
END LOOP;
RETURN FALSE ;
END;
$BODY$;
ALTER FUNCTION public.arraycontain(json, json)
OWNER TO postgres;
But when I do this:
select * from "stores"
where arrayContain(stores.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]')
it shows
ERROR: invalid input syntax for type json
DETAIL: The input string
ended unexpectedly.
CONTEXT: JSON data, line 1: SQL state: 22P02
here is the sqlfiddle (I couldn't update the arraycontain function in fiddle.)
My expected output from the fiddle is it should return last 3 rows that is Furbish Studio,Fawn Shoppe AND LOFT if search using this values ["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"])
I am open for any recommendation.
I also tried this query below but it returns empty.
select id
from stores
where string_to_array(categories_id,',') && array['5565bffd-cd78-4e6f-ae13-4bef61af48f5','5565bffd-b1c8-4556-ae5d-4bef61af48f5'];
EDIT:
This code is actually a filter to filter data. So if I only filter using categories it didn't work but if there is a query before it it works
select * from "stores"
where name like '%ab%' and arrayContain(stores.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]')
also the thing that amaze me is that the '%ab%' must contain more than two character if there's below <2 it will throw error. what could be wrong.
Click: demo:db<>fiddle
You can use the ?| operator, which takes a jsonb array (your column in that case) and checks a text array if any elements are included:
SELECT
*
FROM
mytable
WHERE categories_id ?| '{5565bffd-b1c8-4556-ae5d-4bef61af48f5,5565bffd-cd78-4e6f-ae13-4bef61af48f5}'
If your categories_id is not of type json (which is what the error message says) but a simple text array, you can compare two text arrays directly using the && operator:
Click: demo:db<>fiddle
SELECT
*
FROM
mytable
WHERE categories_id && '{5565bffd-b1c8-4556-ae5d-4bef61af48f5,5565bffd-cd78-4e6f-ae13-4bef61af48f5}'
Your code seems to work fine so perhaps sqlfiddle is the problem.
Try changing the separator in the schema building part to / (instead of ;) and make sure you have the correct version for Postgresql. json_array_elements_text is not supported in 9.3 (you can use json_array_elements instead in this case).
Also skip the " in the select statement.
Look here http://sqlfiddle.com/#!17/918b75/1
There might be an error in your data. Perhaps categories_id is an empty string somewhere.
Try this to see the offending data if any.
do $$
declare
r record;
b boolean;
begin
for r in (select * from stores) loop
b:= arrayContain(r.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]') ;
end loop;
exception
when others
then raise notice '%,%',r,r.categories_id;
return;
end;
$$
Best regards.
Bjarni
I have made a function in postgres
CREATE OR REPLACE FUNCTION foobar(
x TEXT,
y TEXT,
z REAL
) RETURNS BOOLEAN AS $func$
.
.
.
$func$ LANGUAGE plpgsql;
When I do \df i get the following:
+----------+--------+------------------+------------------------+---------+
| Schema | Name | Result data type | Argument data types | Type |
+----------+--------+------------------+------------------------+---------+
| mySchema | foobar | boolean | x text, y text, z real | normal |
+----------+--------+------------------+------------------------+---------+
But when I try to use it I get [42883] ERROR: function foobar(text, text, real) does not exist. Hint: No function matches the given name and argument types. You might need to add explicit type casts. The call I'm doing is:
SELECT * FROM myTable WHERE foobar(column1::text, 'hello'::text, 7.2::real);
To me it seems like the function exists and the types match, I'm struggling to figure out what's wrong.
As a_horse_with_no_name mentioned in his comment, the solution is prefix the function with the schema.
Wrong: SELECT * FROM myTable WHERE foobar(column1::text, 'hello'::text, 7.2::real);
Correct: SELECT * FROM myTable WHERE mySchema.foobar(column1::text, 'hello'::text, 7.2::real);
I expected this to be simple, but I've tried multiple combinations and I can't get PostgreSQL to accept them. It claims there are no matching functions, yet the types listed (as seen in the example below) clearly matches my defined function.
List of data types
Schema | Name | Internal name | Size | Elements | Access privileges | Description
--------+--------+---------------+------+----------+-------------------+-------------
public | levels | levels | 4 | debug +| |
| | | | info +| |
| | | | warn +| |
| | | | critical | |
CREATE FUNCTION public."logEvent"(IN in_type text,IN in_priority public.levels,IN in_message text)
RETURNS void
LANGUAGE 'sql'
NOT LEAKPROOF
AS $function$
INSERT INTO public.log (type,priority,message) VALUES (in_type, in_priority, in_message);
$function$;
The failing query:
SELECT 1 FROM public.logEvent('test'::text,'debug'::public.levels,'test from sql prompt'::text);
ERROR: function public.logevent(text, levels, text) does not exist
LINE 1: SELECT 1 FROM public.logEvent('test'::text,'debug'::public.l...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
An alternate function definition: I get the same error when trying to execute this create function call:
CREATE FUNCTION public."logEvent"(IN in_type text, IN in_priority text, IN in_message text)
RETURNS boolean
LANGUAGE 'sql'
NOT LEAKPROOF
AS $function$
SELECT public.logEvent( in_type, CAST(lower(in_priority) AS public.levels), in_message);
$function$;
Are you aware that double-quoted identifiers are case-sensitive?
Are PostgreSQL column names case-sensitive?
CREATE FUNCTION public."logEvent"
But:
SELECT 1 FROM public.logEvent
This should work:
SELECT 1 FROM public."logEvent"('test', 'debug', 'test from sql prompt');
Explicit type casts are only necessary if there can be ambiguity with overloaded function.
Either keep double-quoting "logEvent" for the rest of its existence, or (smarter) use unquoted (effectively lower-case), legal identifiers.