ERRORE: stringa quotata non terminata in corrispondenza o vicino

Mentre eseguo il codice di trigger mostrato sotto usando ANT, sto ottenendo l’errore

org.postgresql.util.PSQLException: ERROR: unterminated quoted string at or near "' DECLARE timeout integer" Position: 57 

Sono in grado di eseguire con successo il codice seguente tramite PGADmin (Fornito da postgres) e l’utilità della riga di comando “psql” e la funzione di triggerszione viene aggiunta ma durante l’esecuzione tramite ANT non riesce ogni volta

 BEGIN TRANSACTION; CREATE OR REPLACE FUNCTION sweeper() RETURNS trigger as ' DECLARE timeout integer; BEGIN timeout = 30 * 24 * 60 * 60 ; DELETE FROM diagnosticdata WHERE current_timestamp - teststarttime > (timeout * ''1 sec''::interval); return NEW; END; ' LANGUAGE 'plpgsql'; -- Trigger: sweep on diagnosticdata CREATE TRIGGER sweep AFTER INSERT ON diagnosticdata FOR EACH ROW EXECUTE PROCEDURE sweeper(); END; 

Ho riscontrato questo errore in Liquibase e questa pagina è stata uno dei primi risultati di ricerca quindi suppongo di condividere la mia soluzione a questa pagina:

Puoi inserire l’intero sql in un file separato e includerlo nel changeset. È importante impostare l’opzione splitStatements su false .

L’intero changeset sarebbe quindi simile

    

Mi piace sempre avere quelle grandi parti SQL (come gli aggiornamenti delle funzioni e così via) in file separati. In questo modo si ottiene l’evidenziazione della syntax corretta quando si apre il file sql e non si deve mescolare XML e SQL in un unico file.


Modifica : come menzionato nei commenti vale la pena notare che la modifica di sql supporta anche l’opzione splitStatements (da thx a AndreyT per averlo indicato).

Ho avuto lo stesso problema con il driver JDBC utilizzato da Liquibase.

Sembra che il driver esploda ogni riga terminata da un punto e virgola e la esegua come un comando SQL separato. Questo è il motivo per cui il codice sottostante verrà eseguito dal driver JDBC nella seguente sequenza:

  1. CREATE OR REPLACE FUNCTION test(text) RETURNS VOID AS ' DECLARE tmp text
  2. BEGIN tmp := "test"
  3. END;
  4. ' LANGUAGE plpgsql

Naturalmente, questo è SQL non valido e causa il seguente errore:

 unterminated dollar-quoted string at or near ' DECLARE tmp text 

Per correggere ciò, è necessario utilizzare i backslash dopo ogni riga terminata con punto e virgola:

 CREATE OR REPLACE FUNCTION test(text) RETURNS void AS ' DECLARE tmp text; \ BEGIN tmp := "test"; \ END;' LANGUAGE plpgsql; 

In alternativa, è ansible posizionare l’intera definizione in un’unica riga.

Sto usando il client HeidiSQL e questo è stato risolto posizionando DELIMITER // prima dell’istruzione CREATE O REPLACE. Esiste anche un’opzione ‘Invia batch in un colpo solo’ in HeidiSQL che raggiunge essenzialmente la stessa cosa.

Questo errore si verifica come un’interazione tra il particolare client utilizzato per connettersi al server e la forma della funzione. Illustrare:

Il seguente codice verrà eseguito senza perdite in Netbeans 7, Squirrel, DbSchema, PgAdmin3

 CREATE OR REPLACE FUNCTION author.revision_number() RETURNS trigger AS $BODY$ begin new.rev := new.rev + 1; new.revised := current_timestamp; return new; end; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; 

Si noti che l’istruzione ‘begin’ viene immediatamente dopo la stringa quotata ‘$’.

Il prossimo codice interromperà tutti i client precedenti tranne PgAdmin3.

 CREATE OR REPLACE FUNCTION author.word_count() RETURNS trigger AS $BODY$ declare wordcount integer := 0; -- counter for words indexer integer := 1; -- position in the whole string charac char(1); -- the first character of the word prevcharac char(1); begin while indexer <= length(new.blab) loop charac := substring(new.blab,indexer,1); -- first character of string if indexer = 1 then prevcharac := ' '; -- absolute start of counting else prevcharac := substring(new.blab, indexer - 1, 1); -- indexer has increased end if; if prevcharac = ' ' and charac != ' ' then wordcount := wordcount + 1; end if; indexer := indexer + 1; end loop; new.words := wordcount; return new; end; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; 

La differenza cruciale nel secondo esempio è la sezione "dichiarazione". Lo stratagem dell'utilizzo di barre posteriori solleva un errore con PgAdmin3.

In sintesi, suggerisco di provare diversi strumenti. Alcuni strumenti, anche se si suppone che stiano scrivendo file di testo, inseriscono elementi invisibili nel testo. Notoriamente ciò si verifica con il BOM Unicode che fermerà qualsiasi file php che tenta di implementare sessioni o spazi dei nomi. Anche se questa non è una soluzione, spero che aiuti.

Ho avuto lo stesso problema con zeos e c ++ builder. La soluzione nel mio caso:
Cambia il delimitatore di proprietà (di solito “;”) in un altro nel componente (class) che ho usato.

 dm->ZSQLProcessor1->DelimiterType=sdGo; 

Forse Ant ha qualcosa di simile.

Questo esempio ha funzionato per me con PostgreSQL 14.1 e HeidiSQL 9.4.0.5125

 DROP TABLE IF EXISTS emp; CREATE TABLE emp ( empname text NOT NULL, salary integer ); DROP TABLE IF EXISTS EMP_AUDIT; CREATE TABLE emp_audit( operation char(1) NOT NULL, stamp timestamp NOT NULL, userid text NOT NULL, empname text NOT NULL, salary integer ); DELIMITER // CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $$ BEGIN -- -- Create a row in emp_audit to reflect the operation performsd on emp, -- make use of the special variable TG_OP to work out the operation. -- IF (TG_OP = 'DELETE') THEN INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*; RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*; RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*; RETURN NEW; END IF; RETURN NULL; -- result is ignored since this is an AFTER trigger END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS emp_audit ON emp; CREATE TRIGGER emp_audit AFTER INSERT OR UPDATE OR DELETE ON emp FOR EACH ROW EXECUTE PROCEDURE process_emp_audit(); 

Stavo ricevendo lo stesso errore perché avevo il mio punto e virgola in una nuova riga come questa:

 WHERE colA is NULL ; 

Assicurati che siano su un’unica riga come

 WHERE colA is NULL; 

So che questa domanda è stata posta molto tempo fa, ma ho avuto lo stesso problema con uno script Postgresql (eseguito da Jenkins) utilizzando l’attività SQL di Ant.

Ho provato a eseguire questo SQL (salvato in un file denominato audit.sql):

 DROP SCHEMA IF EXISTS audit CASCADE ; CREATE SCHEMA IF NOT EXISTS audit AUTHORIZATION faktum ; CREATE FUNCTION audit.extract_interval_trigger () RETURNS trigger AS $extractintervaltrigger$ BEGIN NEW."last_change_ts" := current_timestamp; NEW."last_change_by" := current_user; RETURN NEW; END; $extractintervaltrigger$ LANGUAGE plpgsql ; 

ma ha ottenuto l’errore “stringa senza virgolette non terminata”. Nessun problema durante l’esecuzione da pgAdmin.

Ho scoperto che non è l’autista a dividere lo script in ogni “;” ma piuttosto Ant.

A http://grokbase.com/t/postgresql/pgsql-jdbc/06cjx3s3y0/ant-sql-tag-for-dollar-quoting ho trovato la risposta:

La formica mangia doppio – $$ come parte della sua elaborazione variabile. Devi usare $ BODY $ (o simile) nei proc memorizzati e mettere il delimitatore sulla propria riga (con delimitertype = “riga”). Ant collaborerà allora.

Il mio script Ant SQL si presenta così e funziona: