如何保持循环甚至发生错误?

How to keep looping even error happend?

我写了一个 PL/pgsql 来在 tables

上批量创建索引
CREATE OR REPLACE FUNCTION create_index() RETURNS void AS
$BODY$
DECLARE
    r INTEGER;
BEGIN
    FOR r IN 1..1000
    LOOP
        EXECUTE format(
        ' CREATE INDEX idx_abc_id_' || r::text ||
        ' ON abc_id_' || r::text ||
        ' USING btree
        (key);');
    END LOOP;
    RETURN;
END
$BODY$
LANGUAGE plpgsql;

它有一个问题,如果分区 abc_500 不存在,那么如何创建索引函数将失败并且什么都不做。

即使 create_index 在其中一个 table 上出错,如何使循环继续进行?

我认为更好的方法是不对循环的数字进行硬编码,而是迭代现有的 tables:

CREATE OR REPLACE FUNCTION create_index() RETURNS void AS
$BODY$
DECLARE
    r record;
BEGIN
  FOR r IN select tablename, regexp_replace(tablename, '[^0-9]+','') as idx_nr
            from pg_tables
            where tablename ~ 'abc_id_[0-9]+'
  LOOP
    EXECUTE format('CREATE INDEX %I ON %I USING btree (key)', 
                   'idx_abc_id_'||r.idx_nr, 
                   r.tablename);
  END LOOP;
  RETURN;
END
$BODY$
LANGUAGE plpgsql;

当您使用 format() 函数时,最好使用适当的标识符占位符。

如果您还想在现有 table 上创建索引时忽略任何错误,则需要捕获异常并忽略它:

CREATE OR REPLACE FUNCTION create_index() RETURNS void AS
$BODY$
DECLARE
    r record;
    msg text;
BEGIN
  FOR r IN select tablename, regexp_replace(tablename, '[^0-9]+','') as idx_nr
           from pg_tables
           where tablename ~ 'abc_id_[0-9]+'
  LOOP
    BEGIN
      EXECUTE format('CREATE INDEX %I ON %I USING btree (key)', 
                     'idx_abc_id_'||r.idx_nr, 
                      r.tablename);
    EXCEPTION 
      WHEN OTHERS THEN
        GET STACKED DIAGNOSTICS msg = MESSAGE_TEXT;      
        RAISE NOTICE 'Could not create index for: %, %', r.idx_nr, msg;
    END;
  END LOOP;
  RETURN;
END
$BODY$
LANGUAGE plpgsql;