sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgresql:Hur undkommer man enstaka citattecken i databasutlösaren?

I allmänhet enstaka, citattecken undkomms genom att dubbla dem.

För att sätta samman dina variabler i en SQL-sträng bör du använda quote_literal() - den funktionen tar hand om enstaka citattecken på rätt sätt, t.ex.:

quote_literal(temp_row.row_data)

Med det sagt:den bättre (och säkrare) lösningen är att använda parametrar kombinerade med 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; 

%I platshållaren tar vanligtvis hand om att flykta en identifierare på rätt sätt, även om det i det här fallet inte skulle fungera. Om du vill vara 100 % säker på att även icke-standardiserade tabellnamn fungerar korrekt, måste du först lägga in måltabellens namn i en variabel och använda det för format() funktion:

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

Denna del:

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

kommer att misslyckas efter första raden också. execute .. into ... förväntar sig att frågan returnerar en enkel . Uttrycket du använder returnerar alla rader från historiktabellen.

Jag förstår inte heller varför du gör det i första hand.

Du behöver inte alls välja från historiktabellen.

Något sådant här borde vara tillräckligt (otestat! ):

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;

Slutligen:revisionstriggers har skrivits tidigare, och det finns många färdiga lösningar för detta:




  1. ODP.NET Oracle.ManagedDataAccess orsakar ORA-12537 nätverkssession slutet av filen

  2. Hur visar jag bilder från MySQL-databas i ett JavaScript-bildskjutreglage?

  3. Finns det något sätt att återställa efter commit i MySQL?

  4. Det går inte att ansluta från Intellij till mySql som körs i docker-container - specificerad databasanvändare/lösenordskombination avvisas