sql - 当我有一个很大的结果时,Postgres 函数不工作

标签 sql postgresql function postgresql-9.5

我正在将信息从表 1(tmp_subtype) 复制到表 2(subtype_user)。我有一个带有 15 个寄存器的测试表 1。我将这个函数运行到 postgres 中:

CREATE OR REPLACE FUNCTION VERIFY_AND_INSERT_SUPTYPE()
    RETURNS text AS $$
    DECLARE
       register_subtype RECORD;
       existe INT DEFAULT 0;
       MESSAGE_EXCEPTION TEXT;
       cursor_subtype CURSOR
       FOR
          SELECT tsd.subtype,tsd.type_id_client,tsd.id_client,tsd.email
          FROM tmp_subtype tsd;
    BEGIN

      OPEN cursor_subtype;
      LOOP
         FETCH cursor_subtype INTO register_subtype;
         EXIT WHEN NOT FOUND;

         SELECT COUNT(*) INTO existe FROM (
            SELECT sdu.id_client FROM subtype_user sdu
            WHERE sdu.id_client = register_subtype.id_client AND sdu.type_id_client = register_subtype.type_id_client
            LIMIT 1
         ) SUB0;

         IF existe = 0 THEN
            INSERT INTO subtype_user(subtype,type_id_client,id_client,email)
            VALUES (register_subtype.subtype,register_subtype.type_id_client,register_subtype.id_client,register_subtype.email);
         ELSE
            UPDATE subtype_user sdu2 SET subtype=register_subtype.subtype,email=register_subtype.email
            WHERE sdu2.id_client = register_subtype.id_client AND sdu2.type_id_client = register_subtype.type_id_client;
         END IF;
      END LOOP;
      CLOSE cursor_subtype;

      RETURN 'OK';

      EXCEPTION WHEN OTHERS THEN
            GET STACKED DIAGNOSTICS MESSAGE_EXCEPTION = MESSAGE_TEXT;
            RETURN MESSAGE_EXCEPTION;
    END; $$
    LANGUAGE plpgsql;

它可以工作,但是当我用真正的表 1 运行这个函数时,它不工作。该功能完成但没有任何反应。真实表1有100万个寄存器。

最佳答案

带有嵌入式计数的逐行处理会导致处理缓慢且效率低下。此外,如果从并发事务调用该函数,则您的存在性检查将不起作用。据我所知,您可以用单个 INSERT 语句替换整个循环和游标:

CREATE OR REPLACE FUNCTION VERIFY_AND_INSERT_SUPTYPE()
    RETURNS text 
AS $$
DECLARE
  MESSAGE_EXCEPTION TEXT;
BEGIN

  INSERT INTO subtype_user(subtype, type_id_client, id_client, email)
  SELECT tsd.subtype, tsd.type_id_client, tsd.id_client, tsd.email
  FROM tmp_subtype tsd
  ON conflict (id_client, type_id_client) DO UPDATE 
    SET  subtype = excluded.register_subtype,
         email = excluded.email;

  RETURN 'OK';

  EXCEPTION WHEN OTHERS THEN
        GET STACKED DIAGNOSTICS MESSAGE_EXCEPTION = MESSAGE_TEXT;
        RETURN MESSAGE_EXCEPTION;
END; $$
LANGUAGE plpgsql;

我可能不会一开始就添加异常处理程序,以便调用者看到完整的异常。

关于sql - 当我有一个很大的结果时,Postgres 函数不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57421679/

相关文章:

sql - 什么时候适合使用完全外连接?

sql - 有很多自连接的查询很慢

javascript - 如何更改函数以接受不同类型作为参数

c++ - 函数指针只在main内部起作用?

sql - 如何设置日期时间的一部分

c# - Visual C# 存储过程要求不需要的参数

java.lang.ClassNotFoundException : org. postgresql.Driver问题

function - Go 是否支持函数的类型转换/类型转换?

php - 查询生成器 laravel 中的算术运算

postgresql - Airflow 中的 PostgresOperator 超时