Reputation: 637
I need to create a function like this (scaled down to a minimum) where I send an array of strings that should be matched. But I cant make the query to work.
create or replace function bar(x text[]) returns table (c bigint) language plpgsql as $$
begin
return query select count(1) as counter from my_table where my_field in (x);
end;$$;
and call it like this
select * from bar(ARRAY ['a','b']);
I could try to let the parameter x be a single text string and then use something like
return query execute 'select ... where myfield in ('||x||')';
So how would I make it work with the parameter as an array? would that be better or worse compared to let the parameter be a string?
Upvotes: 2
Views: 8102
Reputation: 656804
Yes, an array is the cleaner form. String matching invites corner cases where the separator is part of the string.
To find strings that match any of the given patterns, use the ANY
construct:
CREATE OR REPLACE FUNCTION bar(x text[]) RETURNS bigint LANGUAGE sql AS $func$ SELECT count(*) -- alias wouldn't be visible outside function FROM my_table WHERE my_field = ANY(x); $func$;
count(*)
is slightly faster than count(1)
. Same result in this query.
Using a plain SQL function (instead of PL/pgSQL). Either has its pros and cons.
Upvotes: 5
Reputation: 34281
That's fixed with the help of unnest
that converts an array to a set (btw, the function doesn't have to be plpgsql):
CREATE OR REPLACE FUNCTION bar(x text[]) RETURNS BIGINT LANGUAGE sql AS $$
SELECT count(1) AS counter FROM my_table
WHERE my_field IN (SELECT * FROM unnest(x));
$$;
Upvotes: 2
Reputation: 637
The problem with using the array seems to be fixed by using
return query select count(1) as counter from my_table where my_field in (array_to_string(x,','));
The point of effiency still remains unsolved.
Upvotes: 0