AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Lesen/Schreiben von BINARY(16) über DataSet
Thema durchsuchen
Ansicht
Themen-Optionen

Lesen/Schreiben von BINARY(16) über DataSet

Offene Frage von "himitsu"
Ein Thema von tumo · begonnen am 25. Jun 2025 · letzter Beitrag vom 26. Jun 2025
Antwort Antwort
tumo

Registriert seit: 28. Apr 2014
47 Beiträge
 
Delphi 10.3 Rio
 
#1

Lesen/Schreiben von BINARY(16) über DataSet

  Alt Gestern, 22:03
Datenbank: MySQL • Version: 9 • Zugriff über: FireDAC
Hallo allesamt,

Ich habe eine MySQL-(kompatible)-Datenbank mit folgender Tabelle:
Code:
CREATE TABLE test(
  id BINARY(16) PRIMARY KEY,
  name VARCHAR(255),
  picture BLOB
);
Wie vielleicht zu erwarten, ist die Spalte "id" für eine UUID/GUID gedacht.
Nun möchte ich Daten in diese einfügen. Aufgrund des geerbten Codes, der stark auf der TDataSet-Klasse aufbaut, muss ich dies über besagte TDataSet-Objekte abfertigen. Folgender Code kam mir da in den Sinn
Delphi-Quellcode:
fConnection := TFDConnection.Create(nil);
fConnection.Open('DriverID=MySQL;Host=localhost;Port=3306;Database=test;User_Name=root');

var Q := TFDQuery.Create(nil);
Q.Connection := fConnection;
Q.Open('SELECT * FROM test LIMIT 0'); // DataSet für Tabelle "test" holen

Q.Append;
Q.FieldByName('id').AsBytes := fGUID.ToByteArray;
Q.FieldByName('name').AsString := fName;

var S := Q.CreateBlobStream(Q.FieldByName('picture'), bmWrite);
try
  S.Size := 0;
  fPngPicture.Position := 0;
  S.CopyFrom(fPngPicture);
finally
  S.Free;
end;
Q.Post;
So wie es da steht, bekomme ich den Fehler, dass das Feld "id" nur Strings der Länge 5 akzeptiert, der gegebene String aber die Länge 6 hat:
[FireDAC][DatS]-32. Überlauf der Spalte[id] mit variabler Länge. Wertlänge - [6], Maximallänge der Spalte - [5]
Ein Blick auf die Datentypen verrät, dass er die Spalte "id" als ftFixedWideChar interpretiert. ftBytes erscheint mir passender.

Definiert man in der Connection noch "CharacterSet=Binary", wird die Spalte als ftFixedChar anerkannt, der Fehler kommt weiterhin, nur mit den Zahlen 16 und 17. Umgeht man diesen Fehler durch Kürzen des Arrays, findet man aber ein viel größeres Problem: "fName" wird nicht in UTF8 konvertiert. Jedenfalls beschwert er sich, dass es sich um keine gültige utf8mb4-Sequenz handelt.

Andererseits kann man auch "CharacterSet=utf8mb4" definieren, ändert nur nix an der Problematik ohne den Parameter.

Nun zur Frage: Wie arbeite ich korrekt mit einem Datenbank-Feld vom Type BINARY/VARBINARY? Entweder er konvertiert mir die Feldgröße weg (16 -> 5) oder er hängt (scheinbar) einen Null-Character an meine Daten und beschwert sich dann, dass die zu lang sind.

Ein weiteres Problem, was ich jetzt nicht mehr nachstellen kann ist, dass er beim definieren von "CharacterSet=utf8mb4" auch den PNG-Stream "konvertiert" hat. Da kam ganz schön viel chinesisch raus.

Zwei Tage googlen haben keine Früchte getragen, scheinbar hat niemand sonst das Problem
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.453 Beiträge
 
Delphi 12 Athens
 
#2

AW: Lesen/Schreiben von BINARY(16) über DataSet

  Alt Heute, 00:15
[EDIT]
Es ist alles Richtig. DU hast gesagt du willst einen STRING, also hat die DB dir auch einen STRING gegeben.
Zitat von BINARY:
Zum Speichern binärer Strings, unabhängig vom Zeichensatz. Wertebereich für M: 0 bis 255. Weiterer Typ: VARBINARY
https://www.schmager.de/mysql.php

Du wolltest bestimmt den Typ "BLOB", bzw. BLOB(16) verwenden?
(einige andere DBMS bieten sogar direkt einen Typen für GUID, inkl. einer automatischen VARCHAR-Konvertierung, falls man sowas braucht)

Aber ja, ich hätte unter "BINARY" auch erstmal was Anderes verstanden
[/EDIT]


DBTypen, welche die Query-Komponente nicht versteht, bzw. nicht implementiert hat, weichen als Ersatz gern auf VARCHAR aus.

Und da UTF-8 in DBMS nunmal statisch 3 (bis 5) Byte pro Char reserviert, passen in 16 Byte zufällig nur 5 Chars rein.
  • entweder du nutzt eine andere DBKomponente, welche z.B. genau auf das gewünschte DBMS ausgelegt ist
  • oder du erstellst selber die TField (TBlobField) und richtest sie passend ein (BlobType=ftBlob)
    (Dank dem neuen MixedMode muß man nun auch nicht mehr ALLE Felder selbst erstellen, sondern nur noch die Nötigen)
  • oder du spielst am TypeMapping rum, wo du selbst ensprechend die DBTypen zum gewüünschten TField-Typ definierst
  • oder ...
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (Heute um 00:27 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz