Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi xe2 und #39 =ZWEI Hochkommas (https://www.delphipraxis.net/170431-delphi-xe2-und-39-%3Dzwei-hochkommas.html)

Ykcim 17. Sep 2012 08:17

Datenbank: MySQL • Version: 5 • Zugriff über: ohne Komponenten

Delphi xe2 und #39 =ZWEI Hochkommas
 
Hallo Zusammen,

ich nutze #39 um in meinen SQL-Anweisungen Hochkommas zu simulieren. Mit TurboDelphi (Delphi 6) wurde dann ein Hochkomma geschrieben.
Ich versuche gerade auf Delphi xe2 Starter umzusteigen und stelle fest, das in Delphi xe2 mit #39 ZWEI Hochkommas erzeugt werden.

Ist das normal?
Warum ist das so?
Was muss ich tun, wenn ich nur ein Hochkomma haben will?
MYSQL versteht die Anweisung zwar trotzdem, aber ich weiß nicht, wie fehleranfällig das wird, weil ich es nicht verstehe.

Vielen Dank und einen schönen Tag

Ykcim

Medium 17. Sep 2012 08:34

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Wie ermittelst du, ob da wirklich zwei Hochkommas bei rum kommen? Nachher ist das nur ein Bug in dieser Methode. Grundsätzlich ist es aber (finde ich) hübscher, Hochkommas mit sich selbst zu escapen. Sprich zwei hintereinander im Delphi-Quelltext ergeben ein Hochkomma:
Delphi-Quellcode:
aString := 'Heute gab''s Pommes Rot-Weiß';
Ausgabe: Heute gab's Pommes Rot-Weiß

Bernhard Geyer 17. Sep 2012 08:51

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Bitte etwas mehr infos: Mit welcher Zugriffskomponente erledigst du deinen MySQL-Zugriff?
Wie schaut dein QUellcode aus?

Sir Rufo 17. Sep 2012 09:19

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Und wie schon x-fach erwähnt :)

Nutze die Parameter für SQL-Abfragen und man braucht keine "Simulation" vor irgendwas, sondern übergibt einfach das was nachher drin stehen soll.

Code:
INSERT INTO Foo (CharField1) VALUES(:CharField1);
Delphi-Quellcode:
FooQuery.ParamByName('CharField1').Value := MyCharFieldValue;
FooQuery.Execute;
Inhalt von MyCharFieldValue
Code:
Heute gab's Pommes rot-weiß

p80286 17. Sep 2012 10:04

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Zitat:

Zitat von Sir Rufo (Beitrag 1183240)
Und wie schon x-fach erwähnt :)

Nutze die Parameter für SQL-Abfragen und man braucht keine "Simulation" vor irgendwas, sondern übergibt einfach das was nachher drin stehen soll.

Es gibt durchaus Situationen (Generierung von Anweisungen) in denen es zu diesen Hochkommaorgien kommen kann. Ist besonders interessant wenn man zwischen ' und " wechseln muß.

Gruß
K-H

Ykcim 17. Sep 2012 21:21

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Hallo Zusammen,

vielen Dank für die Antworten.

Ich greife auf den MySQL-Server via der mysql.pas zu und habe dafür drei Proceduren (connect, ExecQuery und disconnect).

Wenn ich eine query zusammenbastel, und ich möchte in einer where-Anweisung nach einem Text suchen, muss der für den MySQL-Server in Hochkommas stehen.

Beispiel:

select * from Tabelle where Name='Ykcim'

In meinem Delphi-Programm sieht das dann so aus:
Delphi-Quellcode:
query:='select * from Tabelle where Name='+#39+'Ykcim'+#39;


oder wenn Yckim in einer Variable steht:
Delphi-Quellcode:
query:='select * from Tabelle where Name='+#39+Variable+#39;


Das klappte ja auch wunderbar in TurboDelphi. Aber in xe2 werden an der Stelle von #39 zwei Hochkommas gesetzt.

Getestet habe ich das, indem ich den Wert der Variablen "query" ausgelesen habe. Ich habe der Variable aus Spaß mal nur den "Wert" #39 zugewiesen, dann werden auch zwei Hochkommas gesetzt. Das ist dann kein Gänsfüßchen ", sondern wirklich zwei Hochkommas.

Vielen Dank

Ykcim

Medium 17. Sep 2012 22:03

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
"Ausgelesen" wie?

Schon das Doppelhochkomma statt des #39 probiert?

Edit: Wo kommt die mysql.pas her? Parameter sind imho eine Eigenschaft von SQL, die Unit könnte das ggf. auch implementieren.

*indeinernaserumpul*

Furtbichler 18. Sep 2012 06:31

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Ach, der Debugger zeigt dir 2 Hochkommas an? Super, oder? Der escaped gleich richtig, sodaß Du den String so nehmen und als Stringkonstante irgendwo reinklatschen kannst.

Mit anderen Worten: Das ist kein Bug, das muss so sein.

Delphi-Quellcode:
MyString := 'String mit Hoch''komma';
Showmessage(MyString); // DEbugger auf diese Zeile und dann mit dem Cursor auf MyString

sx2008 18. Sep 2012 06:33

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Wenn du die Parameter wie im Beitrag #4 ignorieren möchtet, dann verwendet wenigstens die Funktion QuotedStr()!
Delphi-Quellcode:
// dynamisches Erzeugen von SQL Abfragen
query:='select * from Tabelle where Name='+QuotedStr(Variable);
Wenn du die Variable query später im Debugger anschaust, kann es durchaus sein, dass du zwei Hochkommas siehst, aber das ist absolut in Ordnung.
Delphi-Quellcode:
// folgende Anweisungen bewirken alle das Gleiche (nur unterschiedl. Schreibweise)
s := 'Opa'#39's Hut';
s := 'Opa'+#39+'s Hut';
s := 'Opa''s Hut';

Ykcim 18. Sep 2012 09:00

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Vielen Dank für die Antworten.
Ich werde mich mal mit der Funktion QuotedStr() auseinandersetzen.

Opa hat keinen Hut, aber die Erklärung war gut! ;-)

Aber dennoch sehe ich das Verhalten von #39 verändert von TurboDelphi zu xe2.

Danke
Ykcim

DeddyH 18. Sep 2012 09:13

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Kleiner Hinweis aus der Hilfe zu QuotedStr:
Zitat:

Anmerkung: Verwenden Sie für die Arbeit mit Multibyte-Zeichensätzen (MBCS) stattdessen die Funktion AnsiQuotedStr.

mkinzler 18. Sep 2012 09:34

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Zitat:

Zitat von DeddyH (Beitrag 1183380)
Kleiner Hinweis aus der Hilfe zu QuotedStr:
Zitat:

Anmerkung: Verwenden Sie für die Arbeit mit Multibyte-Zeichensätzen (MBCS) stattdessen die Funktion AnsiQuotedStr.

Für Ansi QuoteStr() und für Nicht-ANSI (Unicode) AnsiQuoteStr(); ist doch logisch. :stupid:

DeddyH 18. Sep 2012 09:42

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Sischa, sischa :mrgreen:

Ykcim 5. Okt 2012 14:28

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
So, ich bin das Problem jetzt eine Zeit aus dem Weg gegangen, stolpere aber wieder einmal drüber...

Wenn ich eine Abfrage mache, könnte sie wie folgt aussehen:


query:='select * from Tabelle where Feld=''Test'';

So kann ich Eure Antworten verstehen, dass ich das mit mehrfachen Hochkommas erledigen kann. Wenn aber der Wert "Test" in einer Variable steht, bekomme ich ein Problem. Das habe ich vor Delphi xe2 folgender Maßen gelöst:


query:='select * from Tabelle where Feld='+#39+Variable+#39;

Da bekomme ich mit Delphi xe2 jetzt nur noch Murks :evil: raus, weil irgendwann zwischen TurboDelphi (Delphi 6) und Delphi xe2 die Änderung vollzogen wurde, dass #39 statt einem Hochkomma (') bei Delphi xe2 zwei Hochkommas ('') (kein Gänsfüßchen) auswirft.

Wie würdet Ihr das Problem lösen? Ich bin nicht mehr in der Lage eine einfache SQL-Anweisung zu generieren, wenn ich dafür keine Lösung finde...:oops::oops::oops:

Vielen Dank

Ykcim

mkinzler 5. Okt 2012 14:34

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Einfachste Lösung: Parameter.
Oder QuotedStr() verwenden

vagtler 5. Okt 2012 14:43

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Jetzt fangen wir aber an uns im Kreis zu drehen...

mkinzler 5. Okt 2012 14:46

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Ja, aber manche muss man die richtige Lösung mind. 10 mal nenne, dass sie es ihm Wert ist als Möglichkeit in Betracht gezogen zu werden.

himitsu 5. Okt 2012 14:53

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Zitat:

Da bekomme ich mit Delphi xe2 jetzt nur noch Murks raus, weil irgendwann zwischen TurboDelphi (Delphi 6) und Delphi xe2 die Änderung vollzogen wurde, dass #39 statt einem Hochkomma (') bei Delphi xe2 zwei Hochkommas ('') (kein Gänsfüßchen) auswirft.
Nein, es wurde im Delphi absolut nichts umgebaut.
(höchstens einige Debugtools, ala Variablenanzeigen, wurden überarbeitet und zeigen Vieles jetzt "fehlerfreier" an)

Delphi-Quellcode:
query := 'select * from Tabelle where Feld=''Test''';

Variable := 'Test';
query := 'select * from Tabelle where Feld=''' + Variable + '''';

query := 'select * from Tabelle where Feld='#39 + Variable + #39;
'' (in einem String) und #39 oder #$27, Ord(39) usw. sind grundsätzlich genau das Selbe.
Es sind schon immer Kodierungen, um ein ' darzustellen.
In anderen Sprachen sieht man z.B. stattdessen \' , wo dann \\ für ein \ stünde


Raus kommt hier immer
Code:
select * from Tabelle where Feld='Test'


Wenn möglich solltest du ganz einfach parametrisierte Abfragen verwenden (so wie es schon öfters genannt wurde)
und falls das nicht unterstützt wird, dann das entsprechende "QuoteString", welches im String die ' ergänzt.
z.B.
Delphi-Quellcode:
query := 'select * from Tabelle where Feld=' + QuoteString(Variable);
Bei einer "ordentlichen" Zugriffskomponente, kommt dann z.B. sowas bei raus
Delphi-Quellcode:
query.Sql.Text := 'select * from Tabelle where Feld = :wert';
query.ParamByName('wert').Value := 'Test';
Wenn dein mySql so arbeitet, wie ich es noch vom PHP+mySQL kenn, dann wohl eher so
Delphi-Quellcode:
query.Sql.Text := 'select * from Tabelle where Feld = ?';
query.Params[0].Value := 'Test';
In dem Parameter können dann soviele Sonderzeichen und vorallem Steuerzeichen drin vorkommen, wie sie wollen.
Bei QuoteString wird davon vieles abgefangen und wenn man das ohne irgendwas selbst zusammenbaut, dann hat man ganz schnell ein rießiges "Sicherheitsproblem".
Stichwort SQL-Injection.

p80286 5. Okt 2012 15:14

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Zitat:

Zitat von Ykcim (Beitrag 1185925)
Wenn ich eine Abfrage mache, könnte sie wie folgt aussehen:


query:='select * from Tabelle where Feld=''Test'';

Wenn deine Quelltextzeile so aussieht sollte es mindestens eine Fehlermeldung geben, da die Anzahl der Hovhkommata nicht stimmt!

Delphi-Quellcode:
query:='select * from Tabelle where Feld=''Test''';
ergibt
SQL-Code:
select * from Tabelle where Feld='Test'
eine Möglichkeit mit Parametern könnte so aussehen:
Delphi-Quellcode:
query:='select * from Tabelle where Feld=:myfeld;
.params.Parambyname('myfeld').asstring:='Test'; {oder so ähnlich}
ergibt
SQL-Code:
select * from Tabelle where Feld='Test'
und jetzt begründe bitte einmal warum die vielen bisher gezeigten Möglichkeiten für Dich nicht in Frage kommen.
Ohne das haben wir keine Möglichkeit Dir weiter zuhelfen.

Gruß
K-H

Ykcim 5. Okt 2012 15:30

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

Danke für die Antworten.

Ich muss glaube ich mal generell etwas erklären: Ich schätze jede Antwort und versuche alle Antworten zu verstehen - über die Erfolgsquote meiner Bemühung sage ich jetzt lieber nichts...
Dazu habt Ihr mir in diesem Forum schon viel zu viel beigebracht, aber wie bereits angedeutet, verstehe ich als Hobbyprogrammierer oft nicht was damit gemeint ist...
So auch mit der Hilfestellung, dass ich QuotedStr() verwenden soll.

Ich verwende keine Komponenten, um auf den MySQL-Server zu zugreifen, da ich keine habe und auch noch nicht geblickt habe, wie ich dann damit umgehen muss. Sorry, aber ich weiß es wirklich nicht und konnte es mir trotz vieler Suchstunden nicht zusammenlesen.

Ich habe eine umfangreiche Anwendung ohne Komponenten seid 1 Jahr im Produktiveinsatz laufen und dachte, dass ich das auch unter xe2-Starter schaffen könnte.

Ich habe in der Liste der überwachten Objekte festgestellt, dass #39='' statt ' ergibt. Ob das jetzt der Wahrheit entspricht, weiß ich nicht. Ich habe eine Screenshot angehängt, auf dem Ihr es sehen könnt.
Wenn ich aber einem Editfeld #39 als Text zuweise, dann kommt wie üblich nur '. Also, ich weiß jetzt nicht, wo der Fehler liegt...

Ich habe festgestllt, dass #34 (Gänsefüßchen) für den MySQL-Server auch in Ordnung zu sein scheint und daher versuche ich es jetzt mal damit.

ABer vielleicht habt Ihr ja auch noch den ein oder anderen Tip für mich.

Vielen Dank

Ykcim

DeddyH 5. Okt 2012 15:34

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
QuotedStr ist eine Funktion, die hat mit Komponenten nichts zu tun und ist weiter vorn sogar verlinkt.

p80286 5. Okt 2012 15:43

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
diese Funktion gib's seit Delphi7 (man muß nur den richtigen Zeichensatz erwischen (Ansi,Unicode)
Zitat:

Unit

SysUtils

Kategorie

String-Verarbeitung

Delphi-Syntax:

function QuotedStr(const S: string): string;

C++ Syntax:

extern PACKAGE AnsiString __fastcall QuotedStr(const AnsiString S);

Beschreibung

Mit QuotedStr kann der String S in einen String in Anführungszeichen umgewandelt werden. Am Anfang und am Ende von S wird ein halbes Anführungszeichen (') hinzugefügt. Wenn innerhalb des Strings halbe Anführungszeichen enthalten sind, werden diese verdoppelt.

Hinweis: Verwenden Sie für die Arbeit mit Multibyte-Zeichensätzen (MBCS) stattdessen die Funktion AnsiQuotedStr.
Schau mal in Deine OnlineHilfe, was Du da findest.

Gruß
K-H

himitsu 5. Okt 2012 15:48

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Zitat:

Ich habe in der Liste der überwachten Objekte festgestellt, dass #39='' statt '
Da hast du etwas falsch geguckt.
Im String ist nur ein ' enthalten, aber es wird dort so dargestellt, wie man es im Quellcode schreiben würde, also '' im String und dazu noch die beiden ' am Anfang und am Ende.

Wären dort wirklich 2 ' dann würdes du '''' sehn, also
Delphi-Quellcode:
'abc''''def'
statt dem
Delphi-Quellcode:
abc''def
welches wirklich im string wäre.
Wie gesagt, die "Darstellung" dessen wurde überarbeitet, was sich wirklich im String befindet.
So werden nun auch gewisse Steuerzeichen ordentlich und vorallem "sichtbar" dargestellt, wie z.B. Tabulatoren und Zeilenumbrüche.

mkinzler 5. Okt 2012 15:51

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Zitat:

diese Funktion gib's seit Delphi7 (man muß nur den richtigen Zeichensatz erwischen (Ansi,Unicode)
Eine wirklich saubere Lösung wäre aber, eine parametrisierte Abfrage zu verwenden. hierfür findest du unzählige Beispiele hier im forum und im Web bzw. hat sie Frank schon gepostet

p80286 5. Okt 2012 15:52

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Zitat:

Zitat von Ykcim (Beitrag 1185935)
Ich habe in der Liste der überwachten Objekte festgestellt, dass #39='' statt ' ergibt. Ob das jetzt der Wahrheit entspricht, weiß ich nicht. Ich habe eine Screenshot angehängt, auf dem Ihr es sehen könnt.

Das die Textdarstellung etwas gewöhnungsbedürftig ist hat sich noch nicht bis zu Embacadingsbums herum gesprochen. (Proportional-Font bei einer Programmieroberfläche brrr)

Aus Deinen Screenshot leite ich hingegen ab, daß Du vollkommen unproblematisch mit Parametern arbeiten könntest.

Gruß
K-H

och mann alle sind schneller als ich

Edith2:
Das "ohne Komponenten" halte ich für ein Gerücht, Zeig doch einmal Deine Uses her.

EgonHugeist 5. Okt 2012 20:01

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Jede Datenbank reagiert anders. Nun dreht es sich hier um MySQL. Ok kleinens tutorial, Männers.

Ihr könnt weder x ' zu euren Strings hinzufügen noch diese weglassen, es sei den es sind soganante Identifier.

Zurück zum Thema:

Du willst das ' oder mehrere ' ein einem String speichern und das nicht via Parameter sondern in einer selbst assemblierten Abfrage.

prinzipiel kannst du einen String nur mit #39+String+#39 versehen ABER alle dazwischen liegenden #39 MUSST du ESCAPEN. Sonst kommt MySQL beim splitten deiner Query mit den Tokens durcheinander. MySQL bietet dafür functionen an, die das für dich tun und du mußt nur noch den #39 drumherum setzen. Zeos bietet hierfür die function EscapeString(Value: String): String an. Falls du jedoch die möglichkeit hast direkt mit deiner libmysql zu arbeiten, sollte dir die function mysql_escape_string(PTo, PFrom: PAnsiChar; Len: ULong): ULong; weiterhelfen.

Das problem, welches du hier anschneidest ist weitaus größer als du denkst. Alle diese Datenbanken haben ein unterschiedliches Escaping verhalten mit den jeweils unterschiedlichen CharacterSets. Den Vogel schießt da meines Erachtens nach PostgreSQL ab.

Also grundsätlich HÄNDE weg von AnsiQuotedStr oder QuotedStr! Was die Pascal Compiler verstehen heist NICHT das es die Datenbank versteht.

Nächstes Problem wäre zum Beispiel dieser String '''abc\''abc''', da nun auch der Backslash beim escapen eine enorme Rolle spielt

Fazit: Solltest du explizit nicht wissen, was in deinem String enthalten ist, laß die Datenbank das escapen übernehmen, was Parameterisierte Queries automatisch für dich tun.

dein #39Test#39 String müßte (hoffe das ist jetzt vollkommen richtig) also wie folgt behandelt werden:
select * from tabelle1 where feld1='#39+'\'+#39+'text+'\'+#39+#39 quasi OHNE Pascal Quotes '\'text\''

Wenn das nun alles zu kompliziert wird: Benutze Paramter!

Michael

Sir Rufo 7. Okt 2012 09:14

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Also nach dem ich mir mal diese mysql.pas angesehen habe kann ich ja fast nur noch mit dem Kopf schütteln.

Da gibt es doch tatsächlich Funktionen darinnen um alles mögliche zu Escapen und zu Quoten und zwar "the mysql-way"

Jetzt stellt sich nur noch die Frage, warum werden diese Funktionen nicht benutzt? :roll:

Medium 7. Okt 2012 15:04

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
Na weil doch der String im Debug-Output komisch ist!!! :mrgreen: (scnr)

EgonHugeist 8. Okt 2012 08:03

AW: Delphi xe2 und #39 =ZWEI Hochkommas
 
@Sir Rufo

Hmm warum nutzt die Functionen keiner? Thread-Start + alle anderen Antworten -> es wissen halt zu wenige, daß es diese Funktionen gibt, oder viel mehr hat sich noch keiner damit auseinander gesetzt, wie so eine Query gesplittet wird.

Alle SQL RDBMS haben da das gleich Verhalten. Sobald der Char, welche String-Anfang/Ende signalisiert, oder der Escape-Char sich in diesem String befindet, müssen dies Chars escaped werden.

Simples Beispiel:

insert into Tabelle1 values ('Foo'bar', 'Foo'bar');

MySQL ließt nun jeden Char und erstllt eine Liste von Tokens. Quasi Token.Value/Token.Type.

die ersten Tokens bis zur Klammer übergehe ich mal. Dann folgt beim jetzigen string:

Token.Value = "Foo"
Token.Type = Quoted

Token.Value = "bar"
Token.Type = word -> da ohne Anführungszeichen

Token.Value = ", "
Token.Type = Quoted

Token.Value = "Foo"
Token.Type = word -> da ohne Anführungszeichen

Token.Value = "bar"
Token.Type = Quoted

Also ein riesen Schlamassel, da ALLE SQL Provider davon augehen: Was zwichen den Quotes steht ist DER String. um MySQL zu zwingen über die Half-Quote zu lesen, muß diese Escaped werden. Für die meisten CharSets wird hier der '\' hergenommen. Für Big5 oder GB1080 zum Beispiel ist das unmöglich, da bei den EUC kodierten charsets meisten '\' das zweite Byte darstellt.

Also zum String zurück:

insert into Tabelle1 values ('Foo\'bar', 'Foo\'bar');
...
Token.Value = "Foo'bar"
Token.Type = Quoted

Token.Value = ","
Token.Type = Symbol

Token.Value = " "
Token.Type = WhiteSpace

Token.Value = "Foo'bar"
Token.Type = Quoted

Ihr Seht: MySQL entfernt die Escape Chars auch wieder von selber.

Wenn ihr Abfragen selber strickt, deren Inhalt unbekannt ist, verwendet entweder die Escape-Functionen oder Parameter, welche genau das automatisch machen.

Gruß Michael


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz