循环功能无法正常工作

循环功能无法正常工作,第1张

循环功能无法正常工作

还有 很多 我会做出不同的,并且很大的影响。

表定义

从表定义和命名约定开始。这些主要只是意见:

CREATE TEMP TABLE conta (conta_id bigint primary key, ...);CREATE TEMP TABLE departamento (   dept_id   serial PRIMARY KEY , master_id int REFERENCES departamento (dept_id) , conta_id  bigint NOT NULL REFERENCES conta (conta_id) , nome      text NOT NULL);
要点
  • 您确定需要

    bigserial
    部门吗?在这个星球上几乎没有那么多。一个平原
    serial
    就足够了。

  • 我很少使用

    character varying
    长度限制。与其他一些RDBMS不同,使用限制不会带来任何性能提升。
    CHECK
    如果您确实需要实施最大长度,请添加一个约束。我只是使用
    text
    ,主要是为了省掉麻烦。

  • 我建议使用一种命名约定,其中外键列与引用的列共享名称,因此

    master_id
    代替
    master_fk
    ,等等。还允许
    USING
    在联接中使用。

  • 而且我 很少 使用非描述性的列名

    id
    dept_id
    在这里使用代替。

PL / pgSQL函数

它可以在很大程度上简化为:

CREATE OR REPLACe FUNCTION f_retornar_plpgsql(lista_ini_depts VARIADIC int[])  RETURNS int[] AS$func$DECLARE   _row departamento;          -- %ROWTYPE is just noiseBEGINIF NOT EXISTS (     -- simpler in 9.1+, see below    SELECT FROM pg_catalog.pg_class    WHERe  relnamespace = pg_my_temp_schema()    AND    relname      = 'tbl_temp_dptos') THEN   CREATE TEMP TABLE tbl_temp_dptos (dept_id bigint NOT NULL)   ON COMMIT DELETe ROWS;END IF;FOR i IN array_lower(lista_ini_depts, 1)  -- simpler in 9.1+, see below      .. array_upper(lista_ini_depts, 1) LOOP   SELECT *  INTO _row         -- since rowtype is defined, * is best   FROM   departamento   WHERe  dept_id = lista_ini_depts[i];   ConTINUE WHEN NOT FOUND;   INSERT INTO tbl_temp_dptos VALUES (_row.dept_id);   LOOP      SELECt *  INTO _row      FROM   departamento      WHERe  dept_id = _row.master_id;      EXIT WHEN NOT FOUND;      INSERT INTO tbl_temp_dptos      SELECt _row.dept_id      WHERe  NOT EXISTS (         SELECT FROM tbl_temp_dptos         WHERe dept_id =_row.dept_id);   END LOOP;END LOOP;RETURN ARRAY(SELECt dept_id FROM tbl_temp_dptos);END$func$  LANGUAGE plpgsql;

称呼:

SELECt f_retornar_plpgsql(2, 5);

或者:

SELECT f_retornar_plpgsql(VARIADIC '{2,5}');
  • ALIAS FOR 
    是过时的语法,不鼓励使用。请改用功能参数

  • VARIADIC
    参数使调用更加方便。有关的:

    • 在单个参数中传递多个值
    • 您不需要
      EXECUTE
      没有动态元素的查询。在这里没有收获。
  • 您不需要异常处理即可创建表。在这里引用手册:

提示:与没有

EXCEPTION
子句的块相比,包含子句的块的进入和退出成本要高得多。因此,请不要使用
EXCEPTION
而无需使用。

  • Postgres 9.1或更高版本具有
    CREATE TEMP TABLE IF NOT EXISTS
    。我使用9.0的解决方法来有条件地创建临时表。

话虽如此,这真是 令人 the舌: 您不需要大部分。

带rCTE的SQL函数

即使在Postgres 9.0中,
递归CTE也

使这一过程变得更加 简单

CREATE OR REPLACE FUNCTION f_retornar_sql(lista_ini_depts VARIADIC int[])  RETURNS int[] AS$func$WITH RECURSIVE cte AS (   SELECT dept_id, master_id   FROM   unnest() AS t(dept_id)   JOIN   departamento USING (dept_id)   UNIOn ALL   SELECt d.dept_id, d.master_id   FROM   cte   JOIN   departamento d ON d.dept_id = cte.master_id   )SELECt ARRAY(SELECT DISTINCT dept_id FROM cte)    -- distinct values$func$  LANGUAGE sql;


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5508544.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存