PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Postgresql:Como escapar aspas simples no gatilho do banco de dados?


Em geral simples, as aspas são escapadas ao duplicá-las.

Para colocar suas variáveis ​​em uma string SQL, você deve usar quote_literal() - essa função cuida de escapar corretamente aspas simples, por exemplo:
quote_literal(temp_row.row_data)

Dito isto:a melhor (e mais segura) solução é usar parâmetros combinados com format() :
EXECUTE 
   format('INSERT INTO audit.%I_history values ($1, $2, $3)', tg_table_name)
   using temp_row.action_tstamp_tx, temp_row.action, temp_row.row_data; 

O %I placeholder geralmente cuida de escapar adequadamente um identificador, embora neste caso não funcione. Se você quer ter 100% de certeza de que mesmo nomes de tabelas não padrão funcionam corretamente, você precisa primeiro colocar o nome da tabela de destino em uma variável e usá-la para o format() função:
l_tablename := TG_TABLE_NAME || '_history';
EXECUTE 
   format('INSERT INTO audit.%I_history values ($1, $2, $3)', l_tablename)
   using ....

Esta parte:
v_sql = 'select * from ' || TG_TABLE_NAME::regclass || '_history';
execute v_sql into temp_row;

vai falhar após a primeira linha também. execute .. into ... espera que a consulta retorne um único . A instrução que você está usando retornará todos linhas da tabela de histórico.

Eu também não entendo por que você faz isso em primeiro lugar.

Você não precisa selecionar na tabela de histórico.

Algo assim deve ser suficiente (não testado! ):
IF (TG_OP = 'UPDATE' AND TG_LEVEL = 'ROW') THEN
    temp_row := OLD;
ELSIF (TG_OP = 'DELETE' AND TG_LEVEL = 'ROW') THEN
    temp_row := OLD;
ELSIF (TG_OP = 'INSERT' AND TG_LEVEL = 'ROW') THEN
    temp_row := NEW;
ELSE
    RAISE EXCEPTION '[audit.if_modified] - Trigger func added as trigger for unhandled case: %, %',TG_OP, TG_LEVEL;
    RETURN NULL;
END IF;

execute format ('insert ... values ($1, $2, $3') 
   using now(), SUBSTRING(TG_OP,1,1), temp_row;

Finalmente:os gatilhos de auditoria foram escritos antes e existem muitas soluções prontas para isso: