在plpgsql中循环停止,仅在从java执行时没有错误消息

时间:2013-08-14 15:08:38

标签: java postgresql loops plpgsql postgresql-9.1

我有一个plpgsql脚本(编者注:它实际上是一个函数),它包含一个循环,它删除了由eclipse-link生成的一些表的主键约束。它看起来像这样:

CREATE OR REPLACE FUNCTION remove_tables_constraints()
  RETURNS boolean AS
$BODY$
  DECLARE
    constraint_statment text;
  BEGIN
    FOR constraint_statment IN
      SELECT  'ALTER TABLE '||nspname||'.'||relname||' DROP CONSTRAINT '||conname
         FROM pg_constraint
         INNER JOIN pg_class ON conrelid=pg_class.oid
         INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace
         where relname not in('exclude_table')
         ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END,contype,nspname,relname,conname     LOOP
         raise notice 'remove_tables_constraints run [%]', constraint_statment;
         EXECUTE constraint_statment;
     END LOOP;
    RETURN true;
  END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE COST 100;

select remove_tables_constraints();

使用以下命令执行脚本:

Statement st = connection.createStatement();
st.execute(scriptStringloadedFromFile);

脚本有效(在某些情况下仍然有效) 将表的主键从int更改为uid后,它停止了工作。循环在执行中期暂停,不显示任何错误消息(调试设置为最佳级别)。

奇怪的是,如果我只是将它粘贴到psql shell而不是从代码中执行,那么即使在更改之后脚本也能正常工作。而且,如果我解压缩循环并且只是编写循环执行内联的所有语句,它在从java代码执行它时起作用。

我已经花了几天时间,我对如何继续这一点毫无头绪。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我看到了几个问题:

所有东西放在一起它看起来像这样:

CREATE OR REPLACE FUNCTION remove_tables_constraints()
  RETURNS boolean AS
$func$
DECLARE
   constraint_statment text;
BEGIN
   FOR constraint_statment IN
      SELECT format('ALTER TABLE %s DROP CONSTRAINT %I'
                    , c.oid::regclass, o.conname)
      FROM   pg_constraint o
      JOIN   pg_class      c ON c.oid = o.conrelid
      JOIN   pg_namespace  n ON n.oid = c.relnamespace 
      WHERE  c.relname <> 'exclude_table'       -- just one? then <>
      AND    o.contype = 'p'                    -- only pk constraints
      AND    n.nspname NOT LIKE 'pg%'           -- exclude system schemas!
      AND    n.nspname <> 'information_schema'  -- exclude information schema!
      ORDER  BY n.nspname, c.relname, o.conname -- commented irrelevant item
    LOOP
         RAISE NOTICE 'remove_table_constraints run [%]', constraint_statment;
         EXECUTE constraint_statment;
    END LOOP;
    RETURN TRUE;
END
$func$
LANGUAGE plpgsql;

或者更好,没有循环。在这里,我首先聚合成一个命令列表并执行一次:

CREATE OR REPLACE FUNCTION remove_tables_constraints()
  RETURNS boolean AS
$func$
DECLARE
   _sql text;
BEGIN
   SELECT INTO _sql
          string_agg(format('ALTER TABLE %s DROP CONSTRAINT %I'
                    , sub.tbl, sub.conname), E';\n')
   FROM (
      SELECT c.oid::regclass AS tbl, o.conname
      FROM   pg_constraint o
      JOIN   pg_class      c ON c.oid = o.conrelid
      JOIN   pg_namespace  n ON n.oid = c.relnamespace 
      WHERE  c.relname <> 'exclude_table'       -- just one? then <>
      AND    o.contype = 'p'                    -- only pk constraints
      AND    n.nspname NOT LIKE 'pg%'           -- exclude system schemas!
      AND    n.nspname <> 'information_schema'  -- exclude information schema!
      ORDER  BY n.nspname, c.relname, o.conname -- commented irrelevant item
      LIMIT 10
      ) sub;

   RAISE NOTICE E'remove_table_constraints:\n%', _sql;
   EXECUTE _sql;

   RETURN TRUE;
END
$func$
LANGUAGE plpgsql;