Isso começou como uma pergunta sobre índices, mas quando recebi minha resposta , percebi que teria que tentar converter a resposta para a sintaxe 8.4 (não acredito que esse formato não exista).
Achei que estava lidando com as variáveis corretamente, mas por algum motivo não consigo fazer a digitação funcionar corretamente:
CREATE OR REPLACE FUNCTION add_column(schema_name TEXT, table_name
TEXT, column_name TEXT, data_type TEXT) RETURNS BOOLEAN AS $BODY$
DECLARE _tmp text;
BEGIN
EXECUTE 'SELECT COLUMN_NAME FROM information_schema.columns WHERE
table_schema='''+|| schema_name+'''
AND table_name='''+||table_name+'''
AND column_name='''+||column_name+'''' INTO _tmp;
IF _tmp IS NOT NULL THEN
RAISE NOTICE USING MESSAGE = 'Column '+||column_name+' already exists in '+||schema_name+'.'+||table_name;
RETURN FALSE; END IF;
EXECUTE format('ALTER TABLE %I.%I ADD COLUMN %I %s;', schema_name,
table_name, column_name, data_type);
RAISE NOTICE USING MESSAGE = 'Column '+||column_name+' added to '+||schema_name+'.'+||table_name;
RETURN TRUE;
END; $BODY$ LANGUAGE 'plpgsql';
Aqui está a mensagem de erro que recebo:
ERRO: operador não existe: texto + desconhecido
Alguém sabe como posso fazer isso funcionar no 8.4?
Sua função teve vários problemas. Experimente esta versão revisada:
Testado com PostgreSQL 9.1.7.
Você não precisa de SQL dinâmico para verificar a(s) tabela(s) do catálogo quanto à existência da coluna.
EXISTS
Simplifique isso para uma expressão simples .É regularmente mais rápido em duas ordens de magnitude usar a tabela
pg_catalog.pg_attribute
em vez da exibição inchadainformation_schema.columns
.information_schema
é bom apenas para conformidade com o padrão SQL e portabilidade do código. Como você está escrevendo código 100% específico do Postgres em uma função plpgsql, nenhum dos dois é relevante aqui. E o layout básico de pg_attribute também não será alterado nas principais versões do Postgres.format()
foi introduzido com o Postgres 9.1 . Use esta função conveniente no Postgres moderno. Para a versão 8.4 e anteriores, use a alternativa comentada no código.Não cite o nome do idioma
plpgsql
no final! É um identificador, não um valor. Aspas simples Farão o comando falhar ao usar letras maiúsculas. Geralmente, é essencial saber a diferença entre identificadores e valores.Substituí os dois parâmetros
schema_name text, table_name text
porfullname regclass
. Isso tem várias vantagens e nenhuma desvantagem AFAICS.regclass
verifica a existência da tabela imediatamente e gera uma exceção se não. Também impede SQLi de forma eficaz.search_path
será usado automaticamente. Se o nome da tabela for inequívoco, dado o atualsearch_path
, o nome do esquema também não será impresso quando convertido em texto.text
, o esquema e/ou o nome da tabela são automaticamente colocados entre aspas quando necessário. Elimina a necessidade dequote_ident()
, escapando como identificadorformat()
ou adicionando aspas em mensagens.Da mesma forma, eu uso
regtype
para o arquivodata_type
. Vantagens semelhantes. Leia mais sobre os tipos de identificador de objeto no manual.RAISE
Sintaxe mais simples .O operador de concatenação no Postgres (e no SQL padrão) é
||
.+
é uma extensão do padrão no SQL Server que não funciona com a maioria dos outros RDBMS.Isso funciona (não testado extensivamente):
Eu simplesmente removi os sinais + e substituí por ||. No EXECUTE removi o formato e simplesmente concatenei as strings.