PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Postgresql:Wie kann man einfache Anführungszeichen im Datenbank-Trigger maskieren?

Im Allgemeinen werden einzelne Anführungszeichen durch Verdoppelung maskiert.

Um Ihre Variablen in einen SQL-String zu verketten, sollten Sie quote_literal() verwenden - Diese Funktion kümmert sich um das richtige Escapezeichen für einfache Anführungszeichen, z. B.:

quote_literal(temp_row.row_data)

Allerdings:Die bessere (und sicherere) Lösung ist die Verwendung von Parametern in Kombination mit 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; 

Der %I Platzhalter sorgt normalerweise dafür, dass ein Bezeichner ordnungsgemäß maskiert wird, obwohl dies in diesem Fall nicht funktionieren würde. Wenn Sie 100 % sicher sein wollen, dass auch nicht standardmäßige Tabellennamen richtig funktionieren, müssen Sie zuerst den Zieltabellennamen in eine Variable einfügen und diese für das format() verwenden Funktion:

l_tablename := TG_TABLE_NAME || '_history';
EXECUTE 
   format('INSERT INTO audit.%I_history values ($1, $2, $3)', l_tablename)
   using ....

Dieser Teil:

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

wird auch nach der ersten Reihe versagen. execute .. into ... erwartet, dass die Abfrage eine Single zurückgibt . Die von Ihnen verwendete Anweisung gibt all zurück Zeilen aus der Verlaufstabelle.

Ich verstehe auch nicht, warum du das überhaupt machst.

Sie müssen überhaupt nicht aus der Verlaufstabelle auswählen.

So etwas sollte ausreichen (ungetestet! ):

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;

Abschließend:Audit-Trigger wurden bereits geschrieben, und es gibt viele fertige Lösungen dafür: