在postgresql函数中选择case内部的查询

时间:2015-10-27 12:41:03

标签: postgresql

我一直在寻找一段时间,尝试在SO中找到很多代码,但没有一个能够工作。所以我问了一个新问题。

在PostgreSQL函数中,我试图返回一个SETOF bigint(一堆表中的id),但是根据第一个输入($1),查询会有所不同。所以我在该函数中也有一个SELECT CASE

目前,该功能如下所示:

CREATE OR REPLACE FUNCTION get_employee_ids(int, int, int, int, text, int)
RETURNS SETOF bigint AS
$BODY$
    SELECT CASE 
        WHEN $1 = 1 THEN
            SELECT employee_id FROM employee WHERE period = $2 AND payment >= $3 AND operation = $4
            INTERSECT
            SELECT employee_id FROM employee WHERE period IN $5
        WHEN $1 = 2 THEN
            SELECT employee_id FROM employee WHERE period BETWEEN $1 AND $6 AND payment >= $2 AND operation = $3
            INTERSECT
            SELECT employee_id FROM employee WHERE period IN $5
        WHEN $1 = 3 THEN
            SELECT employee_id FROM employee WHERE period BETWEEN $1 AND $6 AND payment >= $2 AND operation != $3
            INTERSECT
            SELECT employee_id FROM employee WHERE period IN $5
        WHEN $1 = 4 THEN
            SELECT employee_id FROM employee WHERE period BETWEEN $1 AND $6 AND payment < $2 AND operation = $3
            INTERSECT
            SELECT employee_id FROM employee WHERE period IN $5
    END
$BODY$
LANGUAGE sql VOLATILE;

在这种情况下,错误是SELECT附近的语法错误。 问题似乎是SELECT没有执行。但我也尝试使用RETURN QUERYEXECUTERETURN QUERY EXECUTE以及其他答案中的许多其他内容。

我该如何做到这一点?

修改 有用的信息,这就是我使用这个函数的方式:get_employee_ids(4, 1108, 250, 97, "(1109,1110)", 0808)

2 个答案:

答案 0 :(得分:2)

使用@klin建议的整数数组和更简单的查询:

create or replace function get_employee_ids (
    int, int, int, int, int[], int
) returns setof bigint as
$body$

select employee_id
from employee
where
    (
        ($1 in (1, 4) and payment < $2 and operation = $3)
        or
        ($1 = 2 and payment >= $2 and operation = $3)
        or
        ($1 = 3 and payment >= $2 and operation != $3)
    )
    and period = ANY ($5)
    and period between $1 and $6

$body$
language sql volatile;

顺便说一下,它似乎可以stable代替volatile

答案 1 :(得分:1)

第五个参数是一个文本,它将成为查询的一部分。您不能以这种方式构建查询。 将参数类型更改为integer[],然后使用ANY代替IN

CREATE OR REPLACE FUNCTION get_employee_ids(int, int, int, int, int[], int)
RETURNS SETOF bigint AS
$BODY$
    SELECT CASE 
        WHEN $1 = 1 THEN
            (SELECT employee_id FROM employee WHERE period = $2 AND payment >= $3 AND operation = $4
            INTERSECT
            SELECT employee_id FROM employee WHERE period = ANY ($5))
        WHEN $1 = 2 THEN
            (SELECT employee_id FROM employee WHERE period BETWEEN $1 AND $6 AND payment >= $2 AND operation = $3
            INTERSECT
            SELECT employee_id FROM employee WHERE period = ANY ($5))
        WHEN $1 = 3 THEN
            (SELECT employee_id FROM employee WHERE period BETWEEN $1 AND $6 AND payment >= $2 AND operation != $3
            INTERSECT
            SELECT employee_id FROM employee WHERE period = ANY ($5))
        WHEN $1 = 4 THEN
            (SELECT employee_id FROM employee WHERE period BETWEEN $1 AND $6 AND payment < $2 AND operation = $3
            INTERSECT
            SELECT employee_id FROM employee WHERE period = ANY ($5))
    END
$BODY$
LANGUAGE sql VOLATILE;

-- usage:
SELECT get_employee_ids(4, 1108, 250, 97, array[1109,1110], 0808);