参数化顺序不在postgresql中工作

时间:2017-02-24 14:21:19

标签: database postgresql sql-parametrized-query sql-order-by

我是postgresql的新人。我试图编写一个postgresql函数进行搜索,只返回匹配的ID,并将订单ID作为参数中提供的列名。

我试图以不同的方式解决问题。

如果排序列不在结果集中,我已经在有条件的情况下读取该订单。但是我写的下面的函数,如果在DB中提供的列类型是文本/字符变化/日期,则返回 ASC 排序中的ID,我测试了。对于整数/浮点类型列,根本不对ID进行排序。现在,我需要根据需要对整数/浮点类型列以及 ASC / DESC 进行排序。

CREATE OR REPLACE FUNCTION public.search_products(_name text DEFAULT NULL::text, _category_id integer DEFAULT NULL::integer, _min_mrp double precision DEFAULT NULL::double precision, _max_mrp double precision DEFAULT NULL::double precision, _sort_field text DEFAULT NULL::text)
 RETURNS SETOF bigint
 LANGUAGE sql
AS $function$

    select product.id 
        from product
        where
            case
                when _category_id is null then (_name is null or lower(product.name) like '%'|| lower(_name) ||'%' and (_min_mrp is null or _max_mrp is null Or (product.market_retail_price BETWEEN _min_mrp and _max_mrp)))
                when _category_id is not null then (_name is null or lower(product.name) like '%'|| lower(_name) ||'%' and (_min_mrp is null or _max_mrp is null Or (product.market_retail_price BETWEEN _min_mrp and _max_mrp))) /*will be updated after category id deciding */
            end

            ORDER BY
                CASE 
                    WHEN(_sort_field similar to 'market_retail_price asc') THEN product.market_retail_price || ' ASC' /* it is float type column, and not working for asc/desc anything */
                    WHEN(_sort_field similar to 'approved_by asc') THEN product.approved_by || ' ASC' /* it is integer type column, and not working for asc/desc anything */
                    WHEN(_sort_field similar to 'approved_on asc') THEN product.approved_on || ' ASC' /* date type column, it works for asc order only. Even if text is 'approved_on desc' in other case, it match the case, but returns data in asc order only. THAT'S TOTALLY WIERED. Never sort desc. */
                    WHEN(_sort_field similar to 'supplier_id asc') THEN product.supplier_id || ' ASC'
                    WHEN(_sort_field similar to 'product_status asc') THEN product.product_status || ' ASC' /* text type, and working for asc only */
                    WHEN(_sort_field similar to 'name desc') THEN (product.name || ' DESC') /* not working for desc order, but returns data in asc sort */
                    ELSE product.id || ' ASC'
                END
$function$

我也试着这样简单地命令:
 ORDERY BY _sort_field
ORDER BY quote_ident(_sort_field);
如果类型为text / date / integer / float,它不会为任何列排序asc / desc!

我正在使用postgresql-9.5.1-1-windows-x64版本

2 个答案:

答案 0 :(得分:2)

ascdesc是关键字,不得包含在排序表达式中。这个数组技巧将会这样做:

order by
    (array [
        to_char(p.market_retail_price, '00000000009'),
        p.approved_by,
        to_char(p.approved_on, 'YYYY-MM-DD'),
        to_char(p.supplier_id, '00000000009'),
        p.product_status
    ])
    [array_position (
        array [
            'market_retail_price asc',
            'approved_by asc',
            'approved_on asc',
            'supplier_id asc',
            'product_status asc'
        ], _sort_field
    )] asc,
    (array [p.name])[array_position (array ['name desc'], _sort_field)] desc

答案 1 :(得分:0)

最后,我使用动态查询解决了我的问题(尽管动态查询很痛苦)。如果没有动态查询,我无法将orderby( ASC DESC )问题修复为提供的参数。这是修改后的功能。谢谢@ ClodoaldoNeto。和另一个实际指示我使用动态查询的人。

这是功能,希望这也有助于其他人:

CREATE OR REPLACE FUNCTION public.search_products(_name text DEFAULT NULL::text, _category_id integer DEFAULT NULL::integer, _min_mrp double precision DEFAULT NULL::double precision, _max_mrp double precision DEFAULT NULL::double precision, _sort_column_name text DEFAULT NULL::text, _sorting_type text DEFAULT 'asc'::text)
 RETURNS SETOF bigint
 LANGUAGE plpgsql
AS $function$
BEGIN

    if($1 is not null) then
        $1 := '%'||$1||'%';
    end if;

    RETURN QUERY EXECUTE
    'SELECT product.id
    FROM product
    WHERE (($1 is null OR product.name ~~* $1) AND ($3 is null OR $4 is null OR (product.market_retail_price BETWEEN $3 and $4)) AND ( $2 IS NULL OR (product.id IN (SELECT product_category_map.product_id FROM product_category_map where product_category_map.category_id = $2))))
    ORDER BY ' 
        || quote_ident($5) 
        || ' '
        || $6
    USING _name, _category_id, _min_mrp, _max_mrp, _sort_column_name, _sorting_type; 

END;
$function$