Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings (https://www.delphipraxis.net/202403-firedac-execsql-uebernimmt-parameter-als-ansi-strings.html)

Der schöne Günther 30. Okt 2019 16:05

Datenbank: Sqlite • Version: 3.x • Zugriff über: FireDAC

FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Folgendes Minimalbeispiel:

Man werfe auf sein Form1 folgendes:
  • TFDPhysSQLiteDriverLink
  • TFDGUIxWaitCursor
  • TFDConnection

Setze für FDConnection.Params.Database einen Dateipfad seiner Wahl
sowie das Event "AfterConnect":

und nutze folgenden Code:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
   FDConnection1.Connected := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
   donger = '( ͡° ͜ʖ ͡°)';
   statement = 'INSERT INTO [myTable] VALUES(:id, :someText)';
   fieldTypes: TArray<TFieldType> = [TFieldType.ftString, TFieldType.ftWideString];
begin
   FDConnection1.ExecSQL(statement, ['Günther', donger]);
end;

procedure TForm1.handleAfterConnect(Sender: TObject);
const
   buildScript =
      'CREATE TABLE [myTable]('+
      ' [id] TEXT PRIMARY KEY NOT NULL UNIQUE ON CONFLICT REPLACE, '+
      ' [someText] TEXT);';
begin
   // FDConnection1.ExecSQL(buildScript); // nur beim ersten mal wenn die Datei noch nicht existiert
end;

Im Button1.Click füge ich über
Delphi-Quellcode:
TFDConnection.ExecSQL(..)
Werte in die Tabelle ein. "Günther" ist noch ok, "( ͡° ͜ʖ ͡°)" hingegen nicht mehr - Hier kommen nur noch die Klammern richtig in der Datenbank an.

Grund ist dass FireDAC, soweit nichts explitit angegeben ist, für die Parameter wohl einen FeldTyp "String" statt "WideString" annimmt. Kann ich das irgendwo steuern? Was für einen Sinn macht es noch Ansi-Strings zu nehmen?

Ich habe bei der
Delphi-Quellcode:
TFDConnection
die Einstellung Params.StringFormat gefunden und auf Unicode gestellt, aber das macht keinen Unterschied...

TurboMagic 30. Okt 2019 17:05

AW: FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Oha! Ja, das ist wichtig zu wissen!

Uwe Raabe 30. Okt 2019 17:13

AW: FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Funktioniert hier tadellos.

Zeig doch mal die Verbindungsparameter.

Der schöne Günther 30. Okt 2019 18:08

AW: FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich kenne mich mit Datenbanken nicht aus. Was sind denn Verbindungsparameter? Es ist nur Sqlite. Hier einmal eine komplette Konsolenanwendung:

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  System.IOUtils,
  {$REGION 'FireDAC.*'}
  FireDAC.Comp.Client,
  FireDAC.Phys.SQLite,
  FireDAC.Phys.SQLiteDef,
  FireDAC.Stan.Def,
  FireDAC.Stan.Async
  {$ENDREGION}
;

type
   TTest = class
      class procedure RunBuildScript(Sender: TObject);
      class procedure Test();
      class procedure InsertTestValues(const connection: TFDConnection);
   end;


class procedure TTest.Test();
const
   filePath: String = 'y:\myDatabase.db';
var
   connection:   TFdConnection;
   driverLink:   TFDPhysSQLiteDriverLink;
begin
   connection := nil; driverLink := nil;
   try
      connection := TFDConnection.Create(nil);
      driverLink := TFDPhysSQLiteDriverLink.Create(nil);
      connection.DriverName := 'SQLite';
      (connection.Params as TFDPhysSQLiteConnectionDefParams).StringFormat :=
         TFDSQLiteStringFormat.sfUnicode;

      connection.Params.Database := filePath;
      if not TFile.Exists(filePath) then
         connection.AfterConnect := TTest.RunBuildScript;

      connection.Connected := True;
      InsertTestValues(connection);
   finally
      connection.Free(); driverLink.Free();
   end;
end;

class procedure TTest.RunBuildScript(Sender: TObject);
const
   buildScript =
     'CREATE TABLE [myTable]('+
     ' [id] TEXT PRIMARY KEY NOT NULL UNIQUE ON CONFLICT REPLACE, '+
     ' [someText] TEXT);';
begin
   (Sender as TFDConnection).ExecSQL(buildScript);
end;

class procedure TTest.InsertTestValues(const connection: TFDConnection);
const
   donger = '( &#865;° &#860;&#662; &#865;°)';
   statement = 'INSERT INTO [myTable] VALUES(:id, :someText)';
begin
   connection.ExecSQL(statement, ['Günther', donger]);
end;

begin
   try
      TTest.Test();
   except
      on E: Exception do
         Writeln(E.ClassName, ': ', E.Message);
   end;
   WriteLn(sLineBreak, 'end.'); ReadLn;
end.
Führe ich das aus und schaue mir dann mit einem externen Tool (z.B. Sqlite Expert) was in der Datenbank steht erhalte ich das hier: Anhang 51761

Setze ich bei
Delphi-Quellcode:
ExecSQL(..)
explizit die FeldTypen auf Widestring, und nur dann, erhalte ich das hier:
Anhang 51760


Ich bin noch wie der letzte Hinterwäldler auf 10.0 Seattle. Wenn das in einer neueren Version besser ist dann wäre das ja erfreulich.

Uwe Raabe 30. Okt 2019 18:50

AW: FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1450550)
Ich bin noch wie der letzte Hinterwäldler auf 10.0 Seattle. Wenn das in einer neueren Version besser ist dann wäre das ja erfreulich.

In der Tat! Mit Seattle kann ich den Fehler reproduzieren, mit Tokyo funktioniert es aber.

TurboMagic 30. Okt 2019 20:35

AW: FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Auch das ist gut zu wissen! ;-)
Danke für den Test Uwe!

Der schöne Günther 30. Okt 2019 20:36

AW: FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Cool.
Für vielleicht noch dieses Jahr stehen längst überfällige Updates der Bibliotheken und Tools (darunter RAD Studio) an. Dann lohnt sich das ja schon wieder ein Stück mehr.

TurboMagic 30. Okt 2019 20:39

AW: FireDAC: ExecSql(..) übernimmt Parameter als Ansi-Strings
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1450560)
Cool.
Für vielleicht noch dieses Jahr stehen längst überfällige Updates der Bibliotheken und Tools (darunter RAD Studio) an. Dann lohnt sich das ja schon wieder ein Stück mehr.

Klar lohnt sich 10.3.x, v.a. wenn du VCL Anwendungen schreibst und die HiDPI fähig
machen willst. Aber das hast du ja auf der Ekon hoffentlich mitbekommen oder gar im
Detail gelernt ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:59 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