String-Literale und Escape-Zeichen in postgresql

112

Der Versuch, ein Escape-Zeichen in eine Tabelle einzufügen, führt zu einer Warnung.

Beispielsweise:

create table EscapeTest (text varchar(50));

insert into EscapeTest (text) values ('This is the first part \n And this is the second');

Erzeugt die Warnung:

WARNING:  nonstandard use of escape in a string literal

( Verwenden von PSQL 8.2 )

Weiß jemand, wie man das umgeht?

rjohnston
quelle

Antworten:

130

Teilweise. Der Text wird eingefügt, aber die Warnung wird weiterhin generiert.

Ich fand eine Diskussion, die darauf hinwies, dass dem Text 'E' als solches vorangestellt werden musste:

insert into EscapeTest (text) values (E'This is the first part \n And this is the second');

Dies unterdrückte die Warnung, aber der Text wurde immer noch nicht korrekt zurückgegeben. Als ich den zusätzlichen Schrägstrich hinzufügte, wie Michael vorgeschlagen hatte, funktionierte es.

So wie:

insert into EscapeTest (text) values (E'This is the first part \\n And this is the second');
rjohnston
quelle
5
Beachten Sie, dass unter PostgreSQL 9.0 E'testing \\ x20double-slash 'als' testing \\ x20double-slash 'ausgewertet wird, sodass nur ein Slash-Ansatz für Literale im E'string-Stil funktioniert
Alexander
2
Für PostgreSQL 9.2 siehe: postgresql.org/docs/9.2/interactive/…
Pitt
psql \copyHinweis: Ich habe festgestellt, dass dies E'\n'als Datei '\n'und nicht als Zeilenumbruch geschrieben wurde, als ich es im Abfrageargument für den Meta-Befehl "\ copy" von psql verwendet habe.
Eintopf
40

Cool.

Ich habe auch die Dokumentation zum E gefunden:

http://www.postgresql.org/docs/8.3/interactive/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS

PostgreSQL akzeptiert auch "Escape" -Stringkonstanten, die eine Erweiterung des SQL-Standards darstellen. Eine Escape-String-Konstante wird angegeben, indem der Buchstabe E (Groß- oder Kleinschreibung) kurz vor dem ersten einfachen Anführungszeichen geschrieben wird, z. B. E'foo '. (Wenn Sie eine zeilenübergreifende Escape-Zeichenfolge konstant fortsetzen, schreiben Sie E nur vor dem ersten öffnenden Anführungszeichen.) Innerhalb einer Escape-Zeichenfolge beginnt ein Backslash-Zeichen (\) eine C-ähnliche Backslash-Escape-Sequenz, in der die Kombination aus Backslash und folgendem Zeichen ( s) repräsentiert einen speziellen Bytewert. \ b ist eine Rücktaste, \ f ist ein Formularvorschub, \ n ist eine neue Zeile, \ r ist ein Wagenrücklauf, \ t ist eine Registerkarte. Ebenfalls unterstützt werden \ digits, wobei digits einen Oktalbytewert darstellen, und \ xhexdigits, wobei hexdigits einen hexadezimalen Bytewert darstellen. (Es liegt in Ihrer Verantwortung, dass die von Ihnen erstellten Byte-Sequenzen gültige Zeichen in der Server-Zeichensatzcodierung sind.) Alle anderen Zeichen nach einem Backslash werden wörtlich genommen. Um ein Backslash-Zeichen einzuschließen, schreiben Sie zwei Backslashes (\\). Zusätzlich zur normalen Art von '' kann ein einfaches Anführungszeichen in eine Escape-Zeichenfolge eingefügt werden, indem \ 'geschrieben wird.

Michael Stum
quelle
6

Die Warnung wird ausgegeben, da Sie Backslashes in Ihren Zeichenfolgen verwenden. Wenn Sie die Meldung vermeiden möchten, geben Sie den folgenden Befehl ein: "set standard_conforming_strings = on;". Verwenden Sie dann "E" vor Ihrer Zeichenfolge, einschließlich Backslashes, die postgresql interpretieren soll.

eppesuig
quelle
1
Nicht wirklich. Wenn ich standard_conforming_strings = aktiviert habe und den Befehl ausführe \copy xxxxxxxxxxx FROM /support01/db/data/xxxxxxxxx_7F.txt DELIMITER AS E'\x7f', erhalte ich parse error at "'\x7f'". Wenn ich die standard_conforming_strings = off habe; und benutze den gleichen Befehl oben ohne das E und die Anführungszeichen ... (DELIMITER AS \ x7f) Ich erhalte die Warnmeldung, aber die Daten werden gut geladen. Ihre Aussage mag also richtig sein, aber in diesem Fall nicht.
Ich habe in SQL-Anweisungen auf Zeichenfolgen verwiesen, während Sie jetzt einen psql-Befehl verwenden. Erhalten Sie den gleichen Fehler mit dem Befehl COPY anstelle von \ copy?
Eppesuig
1
Das ist die richtige Antwort. Moderne Versionen von PG haben es jetzt standardmäßig aktiviert.
jpmc26
3

Ich finde es sehr unwahrscheinlich, dass Postgres Ihre Daten bei der Eingabe abschneidet - es lehnt sie entweder ab oder speichert sie so wie sie sind.

milen@dev:~$ psql
Welcome to psql 8.2.7, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

milen=> create table EscapeTest (text varchar(50));
CREATE TABLE
milen=> insert into EscapeTest (text) values ('This will be inserted \n This will not be');
WARNING:  nonstandard use of escape in a string literal
LINE 1: insert into EscapeTest (text) values ('This will be inserted...
                                              ^
HINT:  Use the escape string syntax for escapes, e.g., E'\r\n'.
INSERT 0 1
milen=> select * from EscapeTest;
          text
------------------------
 This will be inserted
  This will not be
(1 row)

milen=>
Milen A. Radev
quelle
Bitte probieren Sie den Testfall aus, den ich gegeben habe, und Sie werden es selbst sehen.
Johnston
Interessant, sieht so aus, als ob das Problem damals im JDBC-Treiber lag, weil der aus der Datenbank kommende Text definitiv abgeschnitten wurde ...
rjohnston
3
Postgres tut Beendigungsdaten bei der Eingabe in einigen sehr spezifischen Situationen. Beispielsweise schneidet eine character varying(4)Spalte mit der Eingabe "test" (zwei Leerzeichen nach dem Wort, 6 Zeichen) die Leerzeichen ab und speichert den Wert "test". In der Regel können Sie jedoch davon ausgehen, dass Postgres Fehler verursacht, anstatt Ihre Daten abzuschneiden.
Bryson
0

Wirklich dumme Frage: Sind Sie sicher, dass die Zeichenfolge abgeschnitten wird und nicht nur bei dem von Ihnen angegebenen Zeilenumbruch unterbrochen wird (und möglicherweise nicht in Ihrer Benutzeroberfläche angezeigt wird)? Erwarten Sie also, dass das Feld als angezeigt wird?

Dies wird eingefügt \ n Dies wird nicht sein

oder

Dies wird eingefügt

Das wird nicht sein

Welche Schnittstelle verwenden Sie? Ist es möglich, dass etwas auf dem Weg Ihre Backslashes frisst?

Gemeinschaft
quelle
1
das ist mir passiert Der Text wurde in ein Textfeld eingefügt, die Quelle angezeigt, und tatsächlich gab es ein Zitat, und der gesamte Text war vorhanden, nur nicht sichtbar
roberthuttinger