如何从postgresql函数返回查询结果

时间:2015-10-14 10:07:55

标签: postgresql user-defined-functions postgresql-9.4

我是Postgres的新手,在ms sql server中我们可以编写存储过程来执行逻辑并返回一个select语句。同样我写了以下pqsql函数与返回类型表。但是它显示了一些不正确的语法错误,但是如果我用整数替换返回类型并注释掉select语句就可以正常工作。

以下是返回类型表

的函数
CREATE OR REPLACE FUNCTION candidate_save
(
    p_name varchar(50),
    p_dob date,
    p_course_level_code integer,
    p_email varchar(50),
    p_mob character(10),
    p_sslc_regno varchar(10),
    p_sslc_year_of_passing character(4),
    p_sslc_board_of_examination  integer,
    p_password character(128),
    p_ip_address varchar(15)
)
RETURNS TABLE 
(
    regno char(10),
    name varchar(50),
    dob date,
    course_level_code integer,
    email varchar(50),
    mob character(10),
    sslc_regno varchar(10),
    sslc_year_of_passing character(4),
    sslc_boe  integer
)
AS 
$BODY$
DECLARE
    max_row_count integer;
    random_no integer;
    v_regno character(10);
BEGIN

    SELECT COUNT(*) INTO max_row_count FROM candidates WHERE course_level_code = p_course_level_code;

    max_row_count := max_row_count + 1;

    v_regno := cast(p_course_level_code as character) || cast( trunc(random() * 89999 + 10000) as integer) || to_char(max_row_count, 'FM0000');

    INSERT INTO candidates 
        (regno, name, dob, course_level_code, email, mob, sslc_regno, sslc_year_of_passing, sslc_board_of_examination, password, created_on, ip_address)
    VALUES 
        (v_regno, p_name, p_dob, p_course_level_code, p_email, p_mob, p_sslc_regno, p_sslc_year_of_passing, p_sslc_board_of_examination, p_password, now(), p_ip_address);

    RETURN QUERY
        SELECT regno, name, dob, course_level_name, email, mob, sslc_regno, sslc_year_of_passing, c.board as sslc_boe 
        FROM candidates a 
            INNER JOIN course_levels b on a.course_level_code = b.course_level_code
            INNER JOIN sslc_board_of_examinations c ON a.sslc_board_of_examination = boe_code
        WHERE regno = v_regno;

END;
$BODY$
LANGUAGE plpgsql;

创建上述功能时出现以下错误

ERROR:  syntax error at or near "$1"
LINE 1: INSERT INTO candidates ( $1 ,  $2 ,  $3 ,  $4 ,  $5 ,  $6 , ...
                                 ^
QUERY:  INSERT INTO candidates ( $1 ,  $2 ,  $3 ,  $4 ,  $5 ,  $6 ,  $7 ,  $8 , sslc_board_of_examination, password, created_on, ip_address) VALUES ( $9 ,  $10 ,  $11 ,  $12 ,  $13 ,  $14 ,  $15 ,  $16 ,  $17 ,  $18 , now(),  $19 )
CONTEXT:  SQL statement in PL/PgSQL function "candidate_save" near line 30

********** Error **********

ERROR: syntax error at or near "$1"
SQL state: 42601
Context: SQL statement in PL/PgSQL function "candidate_save" near line 30

但如果我用整数替换表,它可以正常工作。

CREATE OR REPLACE FUNCTION candidate_save
(
    p_name varchar(50),
    p_dob date,
    p_course_level_code integer,
    p_email varchar(50),
    p_mob character(10),
    p_sslc_regno varchar(10),
    p_sslc_year_of_passing character(4),
    p_sslc_board_of_examination  integer,
    p_password character(128),
    p_ip_address varchar(15)
)
RETURNS integer
AS 
$BODY$
DECLARE
    max_row_count integer;
    random_no integer;
    v_regno character(10);
BEGIN

    SELECT COUNT(*) INTO max_row_count FROM candidates WHERE course_level_code = p_course_level_code;

    max_row_count := max_row_count + 1;

    v_regno := cast(p_course_level_code as character) || cast( trunc(random() * 89999 + 10000) as integer) || to_char(max_row_count, 'FM0000');

    INSERT INTO candidates 
        (regno, name, dob, course_level_code, email, mob, sslc_regno, sslc_year_of_passing, sslc_board_of_examination, password, created_on, ip_address)
    VALUES 
        (v_regno, p_name, p_dob, p_course_level_code, p_email, p_mob, p_sslc_regno, p_sslc_year_of_passing, p_sslc_board_of_examination, p_password, now(), p_ip_address);

    RETURN 1;

END;
$BODY$
LANGUAGE plpgsql;

如果我做错了事。让我知道。

我正在使用Postgres 9.4

enter image description here

2 个答案:

答案 0 :(得分:1)

INSERT INTO candidates 
    (regno
     ^------- The error

ERROR:  syntax error at or near "$1"
LINE 1: INSERT INTO candidates ( $1

问题是regno是一个plpgsql变量,因为它是输出表中的列名。

RETURNS TABLE 
(
    regno char(10),

RETURNS TABLE中的每个条目都被注册为变量,因此您可以为其分配并使用RETURN NEXT

在解析和处理时,语句中的plpgsql变量将替换为$1$2等位置参数。这就是为什么错误就是它的原因,也是为什么一些后来的条目在插入列名称列表中没有被替换。他们不会与参数名称发生冲突。

使用不同的变量名称。

我认为9.5检测到参数名称冲突并报告更清晰的错误。

答案 1 :(得分:0)

最后,在我更改了返回表中的变量名后,它开始工作了。 感谢所有