问题
I am new to pl/pgsql and trying to create a dynamic query. What I have now is a basic combination of parameters for testing. When it works properly, I will gradually add more dynamic parts, to create a dynamic, all-in-one query.
The problem is that this should work, but instead I see an empty search_creator
as Data Output in the pgadmin4. This is the code
CREATE FUNCTION search_creator(creator text)
RETURNS TABLE(place_id bigint, place_geom geometry, event_name character(200)) AS
$$
BEGIN
RETURN QUERY EXECUTE
'SELECT place.id, place.geom, event.name
FROM person
JOIN event_creator ON event_creator.person_id = person.id
JOIN event ON event.id = event_creator.event_id
JOIN cep ON cep.event_id = event.id
JOIN place ON place.id = cep.place_id
WHERE person.name LIKE $1'
USING creator;
END;
$$
LANGUAGE plpgsql;
This is how I call the function select search_creator('mike');
.
If it helps, in the database, the person.id
column is type character(200)
.
If it helps, when I modify the function to accept int
as input and alter the WHERE
part to WHERE person.id = $1
, then it works fine. I can see actual results in the pgadmin output.
What is wrong with my text variables? Is it the syntax?
Also, how can I do something like WHERE person.name LIKE '%$1%'
?
回答1:
If you run
SELECT search_creator('mike');
the function will execute
SELECT ... WHERE person.name LIKE 'mike'
which is identical to
SELECT ... WHERE person.name = 'mike'
Obviously there is no such record.
To prepend and append %
, you could use
EXECUTE 'SELECT ...
WHERE person.name LIKE ' || quote_nullable('%' || creator || '%');
回答2:
This is how I call the function
select search_creator('mike');
Since the function returns a set (SRF, set-returning function), call it with:
SELECT * FROM search_creator('mike');
If it helps, in the database, the person.id column is type
character(200)
.
It helps. And it hurts. Like I mentioned before, you do not want to use char(n)
(character(n)
). Ever. (Also fix your table.) Read this:
- Any downsides of using data type "text" for storing strings?
Also, how can I do something like
WHERE person.name LIKE '%$1%'
?
Various techniques, but you can simplify with the regular expression match operator ~
, which does the same without leading and trailing wildcard - almost; special characters need to be treated separately for either operator:
CREATE FUNCTION search_creator(_creator text)
RETURNS TABLE(place_id bigint, place_geom geometry, event_name text) AS
$func$
BEGIN
RETURN QUERY EXECUTE
'SELECT pl.id, pl.geom, e.name
FROM person pe
JOIN event_creator ec ON ec.person_id = pe.id
JOIN event e ON e.id = ec.event_id
JOIN cep c ON c.event_id = e.id
JOIN place pl ON pl.id = c.place_id
WHERE pe.name ~ $1' -- note the operator: ~
USING $1;
END
$func$ LANGUAGE plpgsql;
See:
- Difference between LIKE and ~ in Postgres
- Escape function for regular expression or LIKE patterns
- PostgreSQL Reverse LIKE
Follow and read the linked answers and contained references to the manual.
回答3:
below is some working example (Iusednamed IN variables of instead numeric referencing, and format
with concat('%',t,'%')
to build LIKE query:
t=# create or replace function fa(t text) returns table (c text) as
$$
begin
return query execute format($q$select %L::text where 'test' like %L $q$,t,concat('%',t,'%'));
end;
$$ language plpgsql
;
CREATE FUNCTION
Time: 4.412 ms
t=# select * from fa('es');
c
----
es
(1 row)
来源:https://stackoverflow.com/questions/48387285/using-text-in-pl-pgsql-brings-empty-set-of-results