不可能的Postgres循环

时间:2017-02-02 10:38:48

标签: postgresql loops

我有这个Postgres循环:

CREATE OR REPLACE FUNCTIOn insertIds() RETURNS int4 AS '
    DECLARE r RECORD;

    BEGIN
        FOR r IN SELECT id_client FROM client WHERE id_isigeo_util =153 LOOP
               INSERT INTO temps_production VALUES (nextval('temps_production_id_seq'::regclass),(SELECT max(id_livrable) FROM livrable),0,r.id_client,0,now(),0,now(),now());
        END LOOP;
    return 1;
    END;
    ' LANGUAGE plpgsql;
SELECT insertIds() as output;

它给了我这个错误:

 ERROR:  syntax error at or near "temps_production_id_seq"
LINE 6: ...    INSERT INTO temps_production VALUES (nextval('temps_prod...
                                                             ^
********** Erreur **********

ERROR: syntax error at or near "temps_production_id_seq"
État SQL :42601
Caractère : 228

我想将select中包含的每个id复制到一行temps_production中,序列在第一个位置,但是它说错误,它似乎不理解nextval(),但我需要它因为它是一个序列

编辑:关于(SELECT max(id_livrable)FROM livrable),我知道它不好,因为可能会发生并发问题,但是我试图从之前的SQL插入中获取RETURNED变量,并且它给了我一个错误:

 INSERT INTO livrable VALUES (nextval('id_livrable_fid_seq'::regclass),'',now(),now(),'',0,0,0,0,0,0,0,0,0,0,0,0,0,(SELECT max(id_passation)+1 FROM passation),0) RETURNING id_livrable;

这就是我的循环看起来的样子(请注意id_livrable谁应该是来自前一个sql插件的变量......):

        CREATE OR REPLACE FUNCTIOn insertIds() RETURNS int4 
        AS 
        $body$ --<< start of the "dollar quoting"
        DECLARE r RECORD;

        BEGIN
            FOR r IN SELECT id_client FROM client WHERE id_isigeo_util =153 LOOP
               INSERT INTO temps_production VALUES (nextval('temps_production_id_seq'::regclass),id_livrable,r.id_client,0,0,now(),0,now(),now());
            END LOOP;
        return 1;
        END;
        $body$ --< end of the "dollar quoting"
        LANGUAGE plpgsql;

        SELECT insertIds() as output;

错误:

    ERROR:  column "id_livrable" does not exist
LINE 1: ...UES (nextval('temps_production_id_seq'::regclass),id_livrabl...
                                                             ^
HINT:  There is a column named "id_livrable" in table "temps_production", but it cannot be referenced from this part of the query.
QUERY:  INSERT INTO temps_production VALUES (nextval('temps_production_id_seq'::regclass),id_livrable,r.id_client,0,0,now(),0,now(),now())
CONTEXT:  PL/pgSQL function insertids() line 6 at SQL statement
********** Erreur **********

我试过这个:

    DECLARE myid livrable.id_livrable%TYPE;
INSERT INTO livrable VALUES (nextval('id_livrable_fid_seq'::regclass),'',now(),now(),'',0,0,0,0,0,0,0,0,0,0,0,0,0,(SELECT max(id_passation)+1 FROM passation),0) RETURNING id_livrable INTO myid;

但错误:

 ERROR:  syntax error at or near "livrable"
LINE 2: DECLARE myid livrable.id_livrable%TYPE;
                     ^
********** Erreur **********

ERROR: syntax error at or near "livrable"
État SQL :42601
Caractère : 15

编辑2:这是完全正常工作,案件结束谢谢(我也会提供您提供的代码):

CREATE OR REPLACE FUNCTIOn insertIds() RETURNS int4 
        AS 
        $body$ --<< start of the "dollar quoting"
        DECLARE r RECORD;
        DECLARE myid livrable.id_livrable%TYPE;
        BEGIN
        INSERT INTO livrable VALUES (nextval('id_livrable_fid_seq'::regclass),'',now(),now(),'',0,0,0,0,0,0,0,0,0,0,0,0,0,(SELECT max(id_passation)+1 FROM passation),0) RETURNING id_livrable INTO myid;
            FOR r IN SELECT id_client FROM client WHERE id_isigeo_util =153 LOOP
               INSERT INTO temps_production VALUES (nextval('temps_production_id_seq'::regclass),myid,r.id_client,0,0,now(),0,now(),now());
            END LOOP;
        return 1;
        END;
        $body$ --< end of the "dollar quoting"
        LANGUAGE plpgsql;

        SELECT insertIds() as output;

1 个答案:

答案 0 :(得分:0)

您的问题是嵌套的单引号。

为避免使用dollar quoting

的问题
CREATE OR REPLACE FUNCTIOn insertIds() RETURNS int4 
AS 
$body$ --<< start of the "dollar quoting"
DECLARE r RECORD;

BEGIN
    FOR r IN SELECT id_client FROM client WHERE id_isigeo_util =153 LOOP
           INSERT INTO temps_production VALUES (nextval('temps_production_id_seq'::regclass),(SELECT max(id_livrable)+1 FROM livrable),0,r.id_client,0,now(),0,now(),now());
    END LOOP;
return 1;
END;
$body$ --< end of the "dollar quoting"
LANGUAGE plpgsql;

SELECT insertIds() as output;

因此,序列名称所需的嵌入式单引号不需要转义。

但是你不需要循环。一个简单的insert .. select会表现得更好。你应该只运行昂贵的(可能不正确的)select max()一次:

CREATE OR REPLACE FUNCTIOn insertIds() RETURNS int4 
AS 
$body$
DECLARE 
  l_count bigint;

BEGIN
   -- ATTENTION: 
   -- this will not work correctly with concurrent transactions on the livrable table!
   SELECT max(id_livrable)+1 
      into l_count
   FROM livrable;

   INSERT INTO temps_production 
   select nextval('temps_production_id_seq'),
          l_count,
          0, 
          c.id_client,
          0,
          now(),
          0,
          now(),
          now()
    FROM client c
    WHERE id_isigeo_util = 153;

    return 1;
END;
$body$
LANGUAGE plpgsql;

SELECT insertIds() as output;

insert语句中显式声明列也是一种很好的编码风格:

insert into temps_production (id, ....) 
select ...