如何将两个sql语句组合成一个函数

时间:2013-08-02 14:08:09

标签: function postgresql stored-procedures

我试图将我的应用程序代码中的以下两个sql语句组合到postgresql中的函数中,但是我遇到了一些麻烦。 以下是我想要组合的两个SQL查询:

UPDATE userrange f 
SET UsedYesNo = true, user_id=user_id, updateddatetime=now()
WHERE f.uservalue IN(
    SELECT a.uservalue FROM userrange a WHERE UsedYesNo=false Order By id ASC Limit 1)
    RETURNING a.uservalue;

以上语句的结果用于此查询:

   INSERT INTO widget 
   VALUES(DEFAULT, uservalue, 'test','123456778',1,"testservername", now(), Null)

到目前为止,我已经构建了只执行第一个更新语句的函数,如下所示:

CREATE or REPlACE FUNCTION create_widget(IN user_id integer, IN password character varying DEFAULT NULL::character varying)
  RETURNS TABLE(uservalue integer) AS
$BODY$
BEGIN

    RETURN QUERY
UPDATE userrange f SET UsedYesNo = true, user_id=user_id, updateddatetime=now()
    WHERE f.uservalue IN(
    SELECT a.uservalue FROM userrange a WHERE UsedYesNo=false Order By id ASC Limit 1)
    RETURNING a.uservalue;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE

它编译但是当我执行它时,它失败并出现错误:

ERROR:  missing FROM-clause entry for table "a" LINE 4:  RETURNING a.uservalue

我只是在谷歌搜索这个错误,看看我怎么能解决它...但我可以创建一个变量 在DECLARE部分中调用uservalue并在辅助查询中使用它?或者我可以将sql合并为一个

感谢。

1 个答案:

答案 0 :(得分:1)

如果你可以放弃这个功能并且你有PostgreSQL 9.2+,你可以在一个查询中进行更新和插入。如果需要,可以直接将其移植到函数中。

WITH f AS (
    UPDATE userrange f
    SET UsedYesNo = true, user_id=user_id, updateddatetime=now()
    WHERE UsedYesNo IS FALSE
    RETURNING f.uservalue)
INSERT INTO widget (<column list>)
SELECT f.uservalue, 'test','123456778',1,"testservername", now(), NULL
FROM f;

- [编辑:添加功能] - 注意:以下功能未经测试

CREATE OR REPLACE FUNCTION create_widget(IN p_user_id INTEGER, IN p_password VARCHAR DEFAULT NULL::VARCHAR)
RETURNS TABLE(uservalue integer) AS
$BODY$
BEGIN
    RETURN QUERY
        WITH f AS (
            UPDATE userrange f
            SET UsedYesNo = true,
                user_id = p_user_id,
                updateddatetime = now()
            WHERE UsedYesNo IS FALSE
            RETURNING f.uservalue)
        INSERT INTO widget (<column_list>)
        /*  Omit the DEFAULT, by not including it in the column list above,
        *   the DEFAULT already defined on the column will be used.
        */
        SELECT f.uservalue, 'test','123456778',1,"testservername", now(), NULL
        FROM f;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;