plpg sql функция concat необязательные аргументы возвращают ошибку - PullRequest
0 голосов
/ 06 мая 2020

Я хочу объединить необязательные аргументы, разделенные оператором AND, и вернуть varchar тех аргументов объединения, которые не равны нулю.

CREATE OR REPLACE FUNCTION shop_apply_search_filters(price_min INTEGER DEFAULT NULL, price_max INTEGER DEFAULT NULL, ecom_id  INTEGER DEFAULT NULL, 
                                                        cat_1 VARCHAR DEFAULT NULL, cat_2 VARCHAR DEFAULT NULL)
  RETURNS VARCHAR AS
$$
DECLARE final_filters VARCHAR(500);
BEGIN
    IF price_min IS NOT NULL THEN
        SELECT CONCAT('price<',price_min) AS n_price_min;
        final_filters := n_price_min;
    END IF;

    IF price_max IS NOT NULL THEN
        SELECT CONCAT('price>',price_max) AS n_price_max;
        final_filters := CONCAT(final_filters,' AND ', n_price_max);
    END IF;

    IF ecom_id IS NOT NULL THEN
        SELECT CONCAT('ecom_id=',ecom_id) AS n_ecom_id;
        final_filters := CONCAT(final_filters,' AND ', n_ecom_id);
    END IF;

    IF cat_1 IS NOT NULL THEN
        SELECT CONCAT('category_1:',cat_1) AS n_cat_1;
        final_filters := CONCAT(final_filters,' AND ', n_cat_1);
    END IF;

    IF cat_2 IS NOT NULL THEN
        SELECT CONCAT('category_2:',cat_2) AS n_cat_2;
        final_filters := CONCAT(final_filters,' AND ', n_cat_2);
    END IF;

    RETURN final_filters;
END;
$$
LANGUAGE PLPGSQL;

Результатом SELECT shop_apply_search_filters (10) будет строка вида 'цена> 10'. Можно ли передать имя аргумента при вызове функции? Чтобы иметь возможность различать guish price_min и price_max, если передан только один из них. Можно ли добавить в список ненулевые аргументы, а затем присоединить элементы списка с помощью AND?

Как бы вы это сделали?

EDIT

Я удалил SELECT () при CONCAT (), чтобы избежать ошибки. Но у меня есть новый:

ERROR:  query has no destination for result data
HINT:  If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT:  PL/pgSQL function shop_apply_search_filters(integer,integer,integer,character varying,character varying) line 5 at SQL statement
SQL state: 42601

EDIT Я пробовал:

create or replace function shop_apply_search_filters(
    price_min integer default null, 
    price_max integer default null, 
    ecom_id  integer default null, 
    cat_1 text default null, 
    cat_2 text default null)
returns text as
$$
    select concat_ws(
        ' and ',
        'price < '      || price_min,
        'price > '      || price_max,
        'ecom_id = '    || ecom_id,
        'category_1 = ' || cat_1,
        'category_2 = ' || cat_2
    );
$$
language sql;

Он отлично работает со всеми переданными аргументами:

SELECT shop_apply_search_filters(10,10,10,'cat_1','cat_2')

Что делать, если не все аргументы переданы?

SELECT shop_apply_search_filters(10,10,'cat_1','cat_2')

ERROR:  invalid input syntax for integer: "cat_1"
LINE 1: SELECT shop_apply_search_filters(10,10,'cat_1','cat_2')
                                               ^
SQL state: 22P02
Character: 40

SELECT shop_apply_search_filters(10,10)
ERROR:  function shop_apply_search_filters(integer, integer) is not unique
LINE 1: SELECT shop_apply_search_filters(10,10)
               ^
HINT:  Could not choose a best candidate function. You might need to add explicit type casts.
SQL state: 42725
Character: 8

1 Ответ

2 голосов
/ 06 мая 2020

Почему бы просто не использовать concat_ws() для одновременного соединения всей строки?

concat_ws(
    ' and ',
    'price < '      || price_min,
    'price > '      || price_max,
    'ecom_id = '    || ecom_id,
    'category_1 = ' || cat_1,
    'category_2 = ' || cat_2
) 

Затем вы могли бы упростить всю процедуру как:

create or replace function shop_apply_search_filters(
    price_min integer default null, 
    price_max integer default null, 
    ecom_id  integer default null, 
    cat_1 text default null, 
    cat_2 text default null)
returns text as
$$
    select concat_ws(
        ' and ',
        'price < '      || price_min,
        'price > '      || price_max,
        'ecom_id = '    || ecom_id,
        'category_1 = ' || cat_1,
        'category_2 = ' || cat_2
    );
$$
language sql;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...