Então eu executo esta consulta:
SELECT f_copy_tbl('parts','parts1');
...enquanto trabalhava no código baseado nesta resposta e recebo esta mensagem de erro:
ERRO: a relação "partes1" já existe
pgAdmin III não mostra a tabela (e eu obviamente recarreguei a coluna da esquerda pressionando F5 depois de clicar nos itens corretos porque é um efeito de recarga em cascata). Apenas para cobrir minhas bases, eu executo a seguinte consulta:
DROP TABLE IF EXISTS parts1 RESTRICT;
...para o qual o psql retorna:
AVISO: a tabela "partes1" não existe, ignorando
Então, o que é parts1
uma referência senão uma tabela?
Quantas consultas? Todas as consultas:
CREATE OR REPLACE FUNCTION f_copy_tbl(_tbl regclass, _newtbl text)
RETURNS void AS
$func$
BEGIN
-- Copy table
EXECUTE format('CREATE TABLE %I (LIKE %s INCLUDING ALL);', _newtbl, _tbl);
-- Fix serial columns, if any
EXECUTE (
SELECT concat_ws(E'\n'
, string_agg('CREATE SEQUENCE ' || seq, E';\n') || ';'
, string_agg(format('ALTER SEQUENCE %s OWNED BY %I.%I;'
, seq, _newtbl, a.attname), E'\n')
, 'ALTER TABLE ' || quote_ident(_newtbl)
, string_agg(format($$ALTER %I SET DEFAULT nextval('%s'::regclass)$$
, a.attname, seq), E',\n')
)
FROM pg_attribute a
JOIN pg_attrdef ad ON ad.adrelid = a.attrelid
AND ad.adnum = a.attnum
, quote_ident(_newtbl || '_' || a.attname || '_seq') AS seq -- new seq name
WHERE a.attrelid = _tbl
AND a.attnum > 0
AND NOT a.attisdropped
AND a.atttypid = ANY ('{int,int8,int2}'::regtype[])
AND ad.adsrc = 'nextval('''
|| (pg_get_serial_sequence (a.attrelid::regclass::text, a.attname))::regclass
|| '''::regclass)'
);
--Now populate `parts1` table with `parts` table's content...
SELECT f_copy_tbl('parts','parts1');
INSERT INTO parts1 SELECT * FROM parts;
--Now get primary key so we can fix the sequence...
--DECLARE PKEY VARCHAR;
--SELECT pg_attribute.attname INTO PKEY FROM pg_index, pg_class, pg_attribute WHERE pg_class.oid = 'parts1'::regclass AND indrelid = pg_class.oid AND pg_attribute.attrelid = pg_class.oid AND pg_attribute.attnum = any(pg_index.indkey) AND indisprimary;
--Now
--SELECT setval('parts1_' || INTO PKEY || '_seq', (SELECT MAX(pkey) + 1 FROM parts));
/**********
--Now get highest number of primary key *AND* increment it...
--DECLARE PKEY_NUMBER INTEGER;
--SELECT (PKEY + 1) INTO PKEY_NUMBER FROM parts1 ORDER BY PKEY DESC LIMIT 1;
--Fix primary key's autoincrement...
--ALTER SEQUENCE parts1_id_seq RESTART WITH PKEY_NUMBER;
*********/
END
$func$ LANGUAGE plpgsql VOLATILE;
Seu problema é que você definiu uma função recursiva... a função está chamando a si mesma. A lógica que existe nele atualmente resultaria em um despejo de pilha com erro OUT OF MEMORY (ou algo nesse sentido, pelo menos) se não desse o erro de "tabela já existe" para começar.
Sua ordem de SQL deve ser como tal:
A definição da função é o que está entre as cotações do dólar.