如何在PostgreSQL中使用存储过程将数据插入表格

26
CREATE TABLE app_for_leave
(
  sno integer NOT NULL,
  eid integer,
  ename varchar(20),
  sd date,
  ed date,
  sid integer,
  status boolean DEFAULT false,
  CONSTRAINT pk_snoa PRIMARY KEY (sno)
);

基本插入是 ::

INSERT INTO app_for_leave(sno, eid, sd, ed, sid, status)
 VALUES(1,101,'2013-04-04','2013-04-04',2,'f' );

...

INSERT INTO app_for_leave(sno, eid, sd, ed, sid, status) VALUES (?, ?, ?, ?, ?, ?);

我的要求:如何使用存储过程将数据插入表中?


我需要创建一个函数或过程来插入数据到表app_for_leave中。 - 09Q71AO534
Postgres没有存储过程,但它支持函数。 - Mike Christensen
除了使用DML语言查询的INSERT语句,没有其他插入数据的方法吗?还是有其他解决方法吗,@mike christensen? - 09Q71AO534
当然,使用一个函数。 - Mike Christensen
我不确定你在这里问什么。你可以写一个函数来执行INSERT操作。 - mu is too short
这是[SQL FIDDLE](sqlfiddle.com/#!12/3e6a7/18)。请解决这个查询... @muistooshort - 09Q71AO534
4个回答

43

在 PG11 之前,PostgreSQL 不支持存储过程。在那之前,您可以使用函数获得相同的结果。例如:

CREATE FUNCTION MyInsert(_sno integer, _eid integer, _sd date, _ed date, _sid integer, _status boolean)
  RETURNS void AS
  $BODY$
      BEGIN
        INSERT INTO app_for_leave(sno, eid, sd, ed, sid, status)
        VALUES(_sno, _eid, _sd, _ed, _sid, _status);
      END;
  $BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;

您可以这样调用它:
select * from MyInsert(1,101,'2013-04-04','2013-04-04',2,'f' );

Pg的存储函数与真正的存储过程相比,主要受到以下限制:

  1. 无法返回多个结果集
  2. 不支持自主事务(在函数内使用BEGIN、COMMIT和ROLLBACK)
  3. 不支持SQL标准的CALL语法,但ODBC和JDBC驱动程序会为您转换调用。

示例

从PG11开始,引入CREATE PROCEDURE语法,提供了对事务的支持。

CREATE PROCEDURE MyInsert(_sno integer, _eid integer, _sd date, _ed date, _sid integer, _status boolean)
LANGUAGE SQL
AS $BODY$
    INSERT INTO app_for_leave(sno, eid, sd, ed, sid, status)
    VALUES(_sno, _eid, _sd, _ed, _sid, _status);   
$BODY$;

可以这样调用:

CALL MyInsert(1,101,'2013-04-04','2013-04-04',2,'f' );

1
@user2561626 - 首先需要创建该FUNCTION。可以使用我上面提供的示例,在我的服务器上已经验证过可以在Postgres 9.2上运行。 - Mike Christensen
plpgsql不支持自主事务,但其他语言支持,例如plperl。您可以使用dblink和plproxy来实现相同的功能。 - bma
3
Postgres支持多种语言,如PL/pgSQL、Perl、C,甚至有JavaScript扩展。 VOLATILE表示该函数必须每次运行,结果不能被缓存(只有VOLATILE函数可以改变数据库)。这是默认设置,所以我的代码实际上是多余的。 COST为查询规划器提供了一个估计的执行代价。更多细节 - Mike Christensen
http://sqlfiddle.com/#!12/63d9a/1 我刚刚尝试了上面的代码,使用了序列数据类型和一个名称作为函数参数... 然后它显示了一些提示信息... 你能帮我解决吗,@Mike? - 09Q71AO534
1
@lad2025 - 哇,太棒了!我想念和PG一起工作的日子。现在我只用MS SQL Server了,唉... - Mike Christensen
显示剩余6条评论

11

从PostgreSQL 11开始,您可以创建存储过程并使用CALL调用它们:

CREATE PROCEDURE MyInsert(_sno integer, _eid integer, _sd date,
                          _ed date, _sid integer, _status boolean)
LANGUAGE SQL
AS $$
    INSERT INTO app_for_leave(sno, eid, sd, ed, sid, status)
    VALUES(_sno, _eid, _sd, _ed, _sid, _status);   
$$;

CALL MyInsert(1,101,'2013-04-04','2013-04-04',2,'f' );

此外,它还允许处理交易handle transaction

SQL存储过程

PostgreSQL 11引入了SQL存储过程,允许用户在过程中使用嵌套事务(即BEGIN,COMMIT/ROLLBACK)。可以使用CREATE PROCEDURE命令创建过程,并使用CALL命令执行。


很好 @lukasz ... 如何在存储过程中返回结果集,即表格? - Ajt
@Atj 你应该使用一个函数,而不是一个存储的过程 - undefined

2

PostgreSQL不支持存储过程,但是您可以通过使用函数获得相同的结果。

无论您想要插入到表中的数据都可以作为创建的函数的参数来给定。

CREATE OR REPLACE 表示如果具有相同名称(您正在使用)的函数已存在于数据库中,则将替换它,否则,如果不存在具有相同名称的函数,则将创建一个新函数。

您必须在函数体内编写插入查询。

CREATE OR REPLACE FUNCTION Insert_into_table(_sno INTEGER, _eid INTEGER, _ename VARCHAR(20), _sd DATE, _ed DATE, _sid INTEGER)
      RETURNS void AS
      $BODY$
          BEGIN
            INSERT INTO app_for_leave(sno, eid, sd, ed, sid)
            VALUES(_sno, _eid, _sd, _ed, _sid);
          END;
      $BODY$
      LANGUAGE 'plpgsql' VOLATILE
      COST 100;

正如您在表格中提到的那样,该列的默认值为状态现在不需要向该列插入数据

这是您理解的SQLFiddle链接


6
是时候更新这个答案了。PG11支持带事务控制的存储过程,该版本已经发布了几个月。 - DB140141

1
CREATE OR REPLACE FUNCTION  new_bolshek(parent_id bigint, _key text, _value text, enabled boolean)
  RETURNS SETOF bolshekter AS
  $BODY$
  DECLARE
    new_id integer;
    returnrec bolshekter;
  BEGIN
        INSERT INTO bolshekter(parent_id, content_key, content_value, enabled)
        VALUES(parent_id, _key, _value, enabled) RETURNING id INTO new_id;
        FOR returnrec IN SELECT * FROM bolshekter where id=new_id LOOP
            RETURN NEXT returnrec;
        END LOOP;
  END;
  $BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接