Benutzer mit den meisten Antworten
SQLPutData -> Fehler 22001 (String data right truncation)

Frage
-
Guten Tag Zusammen,
ich implementiere in einem ANSI C Programm Lesen und Schreiben der BLOB-Felder von unbekannter Größe (Tabellen-Feld: VARBINARY(MAX)). Die Idee ist - lesen und schreiben in Segmenten und im Programm Speicher nach dem Bedarf allozieren.
Habe die Benutzeranleitung zu den Funktionen SQLBindParameter, SQLParamData, SQLPutData (fürs Schreiben) und SQLGetData (fürs Lesen) mehr oder weniger verstanden. Als Erstes habe ich versucht, ein 40K array mit Ziffern 0-9 zu füllen, in 1К-Segmenten mit SQLPutData zu schreiben, dann Lesen und wieder schreiben - alles funktionierte. Als 2. Schritt habe ich die realen Daten (gespeichertes Bild) gelesen. Größe mit DATALENGTH() geprüft -7233. Beim Lesen - kein Problem. Beim Schreiben auch - solange ich die ersten 7 Segmente schreibe. Aber beim Rest von 233 Bytes kommt ein Fehler 22001 (String data right truncation). Durch Lesen der Fehlerbeschreibung in Microsoft-Doku wurde ich nicht wirklich schlau. Rest vom array nach 7233 Bytes ist mit 0 (binär) gefüllt - warum meint der ODBC-Driver, dass "more data was send for a long parameter... than was specified in the length buffer"??? Ich habe schon alles mögliche versucht - komme aber nicht weiter. Hat jemand eine Idee?
Antworten
-
Ich weiß gar nicht, warum du das segmentierst.
Du kannst einen Puffer und die Länge des Inhaltes genau angeben und an den Treiber übergeben, eine Segmentierung ist nicht erforderlich.Auch per SQLBindParameter übergibst du einen Zeiger für die Länge, sodass die Länge für jeden Aufruf genau angegeben werden kann. Der Pointer zu den Daten ist beim Bind allerdings statisch, so dass du da bereits die max. Länge anlegen musst.
Nachtrag: Ggf. hast du noch den falschen SQL-Typ verwendet:
https://docs.microsoft.com/de-de/sql/odbc/reference/syntax/sqlputdata-function?view=sql-server-ver15Siehe: SQL_LONGVARBINARY
Aber trotzdem mal die Frage:
Warum machst du das Ganze nicht in C#? Da ist das alles sehr viel einfacher.- Bearbeitet Der Suchende Freitag, 18. Dezember 2020 13:07
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Montag, 28. Dezember 2020 08:48
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Montag, 11. Januar 2021 08:44
Alle Antworten
-
Ich weiß gar nicht, warum du das segmentierst.
Du kannst einen Puffer und die Länge des Inhaltes genau angeben und an den Treiber übergeben, eine Segmentierung ist nicht erforderlich.Auch per SQLBindParameter übergibst du einen Zeiger für die Länge, sodass die Länge für jeden Aufruf genau angegeben werden kann. Der Pointer zu den Daten ist beim Bind allerdings statisch, so dass du da bereits die max. Länge anlegen musst.
Nachtrag: Ggf. hast du noch den falschen SQL-Typ verwendet:
https://docs.microsoft.com/de-de/sql/odbc/reference/syntax/sqlputdata-function?view=sql-server-ver15Siehe: SQL_LONGVARBINARY
Aber trotzdem mal die Frage:
Warum machst du das Ganze nicht in C#? Da ist das alles sehr viel einfacher.- Bearbeitet Der Suchende Freitag, 18. Dezember 2020 13:07
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Montag, 28. Dezember 2020 08:48
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Montag, 11. Januar 2021 08:44
-
Ich weiß gar nicht, warum du das segmentierst.
Du kannst einen Puffer und die Länge des Inhaltes genau angeben und an den Treiber übergeben, eine Segmentierung ist nicht erforderlich.Auch per SQLBindParameter übergibst du einen Zeiger für die Länge, sodass die Länge für jeden Aufruf genau angegeben werden kann. Der Pointer zu den Daten ist beim Bind allerdings statisch, so dass du da bereits die max. Länge anlegen musst.
Siehe: SQL_LONGVARBINARY
Aber trotzdem mal die Frage:
Warum machst du das Ganze nicht in C#? Da ist das alles sehr viel einfacher.
-
Hier noch mal einen Link, wie korrekt segmentiert werden muss:
https://docs.actian.com/ingres/10.2/index.html#page/Connectivity/SQLPutData()--Send_Data_in_Segments.htmWas bei einer 32-Bit-Anwendung dann Sinn macht, wenn man mehr Daten senden muss, als mein Prozessspeicher (ca. 1,4GB) überhaupt hergibt.
Bei 64-Bit braucht man das i.d.R. nicht mehr.
- Bearbeitet Der Suchende Dienstag, 22. Dezember 2020 21:55