Using text in pl/pgsql brings empty set of results

痞子三分冷 提交于 2019-12-25 00:53:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!