# BinÃ¤re Daten von max 30 Bytes einfÃ¼gen

**URL:** https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592
**Category:** Allgemeines
**Created:** [13. September 2009 um 12:24 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592 "2009-09-13T12:24:48Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![hronny](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/h/8e8cbc/32.png) [@hronny](https://www.pg-forum.de/u/hronny)
#### Post date: [13. September 2009 um 12:24 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/1 "2009-09-13T12:24:48Z")

</div>

Hallo alle miteinander!

Ich habe schon einiges mit postgresql an Daten gespeichert, aber mit binären Daten musste ich mich bisher nicht auseinandersetzen. Jetzt muss ich aber binäre Daten speichern die pro Datensatz maximal 30 Byte lang sind. Es muss kein Index drauf oder ähnliches. Was nimmt man als Datentyp dafür und wie muss ich das mit ANSI C in die Tabelle einfügen?

Gruß Ronny

---

<div class="post-metadata">

### Author: ![ads](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/8e7dd6/32.png) [@ads](https://www.pg-forum.de/u/ads)
#### Post date: [13. September 2009 um 12:34 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/2 "2009-09-13T12:34:05Z")

</div>

Du nimmst entweder ByteA als Datentyp und schreibst das direkt in die Tabelle oder du encodest das irgendwie (z. B. base64) und speicherst das in einem Feld vom Typ TEXT.

Ach ja, unter Umständen hilft dir noch ein:

```nohighlight
ALTER TABLE ... ALTER COLUMN ... SET STORAGE EXTERNAL;[/quote]
Das verhindert, dass die Daten von PG noch mal komprimiert werden.

Für den Zugriff aus C heraus gibt es PQescapeByteaConn. In ISBN 978-3-937514-69-7 ist die Anwendung ab Seite 284 beschrieben.

```

---

<div class="post-metadata">

### Author: ![hronny](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/h/8e8cbc/32.png) [@hronny](https://www.pg-forum.de/u/hronny)
#### Post date: [13. September 2009 um 17:29 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/3 "2009-09-13T17:29:54Z")

</div>

Also nachdem ich weis nach was ich suchen muss hab ich derzeit folgende Lösung(?) gefunden: Testtabelle anlegen:

```nohighlight
CREATE TABLE testtbl (name text, daten bytea);

```

Daten einfügen:

```nohighlight
uchar buf[255];
unsigned char *to;
int len;

// .......
// Verarbeitung der Daten und ermitteln der Länge usw.
// .......
// Hiermit einfügen

to = PQescapeByteaConn(con, buf, len, &to_len);
sprintf(sqlquery, "INSERT INTO testtbl (name, daten) VALUES ('test', E'%s');", to);

```

---

<div class="post-metadata">

### Author: ![ads](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/8e7dd6/32.png) [@ads](https://www.pg-forum.de/u/ads)
#### Post date: [13. September 2009 um 17:49 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/4 "2009-09-13T17:49:00Z")

</div>

Wieso 255 Zeichen für “buf”?

---

<div class="post-metadata">

### Author: ![hronny](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/h/8e8cbc/32.png) [@hronny](https://www.pg-forum.de/u/hronny)
#### Post date: [13. September 2009 um 18:19 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/5 "2009-09-13T18:19:15Z")

</div>

Dachte ich reserviere schon genug vor, weil die Querys evtl so lang sein könnten. Was könnte evtl besser sein? In der späteren Anwendung werden bis zu 8 INSERT Befehle pro Sekunde zur Datenbank. Deshalb war ich der Meinung ohne malloc/free arbeiten zu können.

Ich freue mich natürlich auch über Verbesserungen. Mit C hab ich es nicht so sehr (arbeite sonst mit Delphi und PHP). Aber in diesem Fall geht es leider nicht anders.

Gruß Ronny

---

<div class="post-metadata">

### Author: ![ads](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/8e7dd6/32.png) [@ads](https://www.pg-forum.de/u/ads)
#### Post date: [13. September 2009 um 18:26 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/6 "2009-09-13T18:26:37Z")

</div>

Nun, “buf” ist in deinem Fall der Speicherplatz für die Daten, die du in die Datenbank schreiben möchtest. Laut deiner Aussage sind das maximal 30 Bytes. Warum reservierst du dann 255 Bytes?

Derartige Programme packe ich eher in die Ecke: ich weiß noch nicht, was letztendlich draus wird, also reserviere ich mal etwas mehr. Später vergesse ich das dann und handle mir einen Segfault samt Absturz und möglicher Code Injection ein.

---

<div class="post-metadata">

### Author: ![hronny](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/h/8e8cbc/32.png) [@hronny](https://www.pg-forum.de/u/hronny)
#### Post date: [13. September 2009 um 20:08 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/7 "2009-09-13T20:08:33Z")

</div>

Ja richtig. Weil die 30 Byte ja “escaped” werden somit im ungünstigsten Fall 150 Bytes belegen. Wenn mein INSERT noch ein wenig komplexer wird, ist das nicht zu übertrieben. Lieber ein paar Bytes zu viel reserviert, als das es hinterher nicht “reinpasst” 😉

---

<div class="post-metadata">

### Author: ![ads](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/8e7dd6/32.png) [@ads](https://www.pg-forum.de/u/ads)
#### Post date: [13. September 2009 um 20:14 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/8 "2009-09-13T20:14:35Z")

</div>

Nein, die 30 Bytes in “buf” bleiben 30 Bytes.

Es wäre fahrlässig, den übergebeben Speicherbereich einfach zu überschreiben, weil die Funktion gar nicht weiß, wie groß der Bereich reserviert wurde.

Nein, für das Ergebnis wird neuer Speicher reserviert, den du später wieder freigeben musst. Den Zeiger darauf bekommst du als Rückgabewert. Steht auch so alles in der Dokumentation.

Selbst wenn jedes einzelne Zeichen escaped wird und selbst wenn der Source-Bereich überschrieben werden würde, kommst du auf maximal 120 Zeichen Länge.  
  
  
Vielleicht wäre es praktisch, wenn du dich vorab mit C beschäftigen würdest. Das ist eine Sprache, in der man sich schnell und gründlich in den Fuß schießen kann. Abgesehen von Assembler und einigen esoterischen Sprachen nimmt keine andere Sprache Programmierfehler so übel wie C.

---

<div class="post-metadata">

### Author: ![symbiont](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/s/ea666f/32.png) [@symbiont](https://www.pg-forum.de/u/symbiont)
#### Post date: [14. September 2009 um 13:42 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/9 "2009-09-14T13:42:56Z")

</div>

> [@hronny](#):
>
> 30 Byte

Was für Informationen sollen denn in den 30 Byte gespeichert werden - wenn ich fragen darf?!

---

<div class="post-metadata">

### Author: ![hronny](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/h/8e8cbc/32.png) [@hronny](https://www.pg-forum.de/u/hronny)
#### Post date: [14. September 2009 um 17:38 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/10 "2009-09-14T17:38:19Z")

</div>

Okay das mit den 255 Bytes reserviert hab ich verstanden. 🙂 Nur wo der Speicher von dem Zeiger reserviert und freigegeben wird, ist mir derzeit völlig unklar. In der Beschreibung steht ja

> PQescapeBytea ergibt eine Version der Binärdaten in from, in der alle Sonderzeichen durch Fluchtfolgen ersetzt wurden, sodass sie vom Zeichenkettenparser und von der bytea-Eingabefunktion ordnungsgemäß verarbeitet werden können. Der Ausgabepuffer wird mit \> **malloc()** \> angelegt. Ein abschließendes Null-Byte wird angehängt.

Würde ja bedeuten, dass ich nach meinem sprintf Befehl den Speicher direkt (selbst) freigeben muss, da sonst beim nächsten Aufruf neuer Speicher reserviert wird.  
Ja ich weis das ist zwar der Befehl **PQescapeBytea** , aber er ist fast genauso wie **PQescapeByteaConn** , steht nur leider nicht in meinem Postgresql Handbuch drin.

> Was für Informationen sollen denn in den 30 Byte gespeichert werden - wenn ich fragen darf?!

In den maximal 30 Bytes (meistens 9-12) werden die einzelnen Bustelegramme erfasst. Da hat fast jedes einzelne Bit eine Bedeutung zuzüglich Prüfsummen etc. Bisher hatte ich die Daten komplett in eine Struktur zerlegt in die Datenbank geschrieben. Dann hab ich festgestellt, dass das übertragen von 1 Mio Daten nach extern (selbst über DSL) viel zu lange dauert. Wenn ich die Daten binär übermittle und dann lokal wieder zerlege, könnte das deutlich schneller sein, als “reine ASCII” Zeichen zu übertragen.

Wichtig sind in der Datenbank eigentlich nur 4 Werte zum Eingrenzen oder Sortieren (Datum, Sender, Befehltyp, Datenwert). Die restlichen Infos sind nicht unwichtig, müssen aber nicht als einzelne Felder in die Datenbank. Somit finde ich es einfacher nur wenig Felder zu nutzen und bei Bedarf die eigentlichen Daten aus dem binären Feld herauszuholen.

---

<div class="post-metadata">

### Author: ![ads](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/8e7dd6/32.png) [@ads](https://www.pg-forum.de/u/ads)
#### Post date: [14. September 2009 um 18:36 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/11 "2009-09-14T18:36:58Z")

</div>

> [@hronny](#):
>
> Nur wo der Speicher von dem Zeiger reserviert und freigegeben wird, ist mir derzeit völlig unklar.

Hatte ich früher schon mal geschrieben: Reservieren tut den die Funktion für dich, freigeben musst du ihn selbst.

> Würde ja bedeuten, dass ich nach meinem sprintf Befehl den Speicher direkt (selbst) freigeben muss, da sonst beim nächsten Aufruf neuer Speicher reserviert wird.

Es wird sowieso neuer Speicher reserviert, egal ob du den freigibst oder nicht.

> Ja ich weis das ist zwar der Befehl \> **PQescapeBytea** \> , aber er ist fast genauso wie \> **PQescapeByteaConn** \> , steht nur leider nicht in meinem Postgresql Handbuch drin.

Du solltest trotz allem **PQescapeByteaConn** verwenden, weil diese Funktion die Einstellungen deiner aktuellen Datenbankverbindung berücksichtigt. Die andere wird vielleicht sogar irgendwann entfernt, darum steht der wohl nicht in deinem Handbuch.

Noch etwas: du solltest jetzt dringend Grundlagen C lernen. Schon anhand deiner Aussagen zeigt sich, dass du einige sehr wichtige Grundlagen der Programmiersprache nicht verstanden hast.

---

<div class="post-metadata">

### Author: ![symbiont](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/s/ea666f/32.png) [@symbiont](https://www.pg-forum.de/u/symbiont)
#### Post date: [14. September 2009 um 18:59 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/12 "2009-09-14T18:59:08Z")

</div>

> [@hronny](#):
>
> Wichtig sind in der Datenbank eigentlich nur 4 Werte zum Eingrenzen oder Sortieren (Datum, Sender, Befehltyp, Datenwert). Die restlichen Infos sind nicht unwichtig, müssen aber nicht als einzelne Felder in die Datenbank. Somit finde ich es einfacher nur wenig Felder zu nutzen und bei Bedarf die eigentlichen Daten aus dem binären Feld herauszuholen.

das riecht danach, als wäre es durchaus denkbar diesen ominösen binär-typ (der wahrscheinlich einem strukturierten typ entstammt ???) doch besser als seine bestandteile zu speichern … wenn ich das recht verstehe, dann besteht dieser aus “komponenten” …

dann speicher doch diese komponenten in jeweils ein geeignetes feld … das sollte sich positiv auf das volumen auswirken - da du ja auch “nullfaehige” komponenten im wert vorzufinden vorgibst … vielleicht sind diese auch noch numerisch … leg doch felder mit den entsprechenden numerischen typen an … davon gibts ja reichlich … und wenn du ein einen teil als bitfeld verwendest der vielleicht 16, oder 32, od 64 bit beansprucht dann nimmst halt den entsprechenden int61, 32, 64 …

denk da mal drueber nach …

dann kannst du dir den ganzen unsinn nämlich schenken

---

<div class="post-metadata">

### Author: ![hronny](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/h/8e8cbc/32.png) [@hronny](https://www.pg-forum.de/u/hronny)
#### Post date: [14. September 2009 um 20:03 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/13 "2009-09-14T20:03:01Z")

</div>

> [@ads](#):
>
> Du solltest trotz allem **PQescapeByteaConn** verwenden, weil diese Funktion die Einstellungen deiner aktuellen Datenbankverbindung berücksichtigt.

Hatte ich auch so geschrieben. Ist vielleicht missverstanden worden, da ich ja **PQescapeByteaConn** benutze. Ich wollte nur damit sagen, das egal ob PQescapeByteaConn oder PQescapeBytea immer ein Zeiger auf den Speicher herauskommt, und ich denke damit liege ich nicht falsch.

> [@ads](#):
>
> Noch etwas: du solltest jetzt dringend Grundlagen C lernen. Schon anhand deiner Aussagen zeigt sich, dass du einige sehr wichtige Grundlagen der Programmiersprache nicht verstanden hast.

Ja einige Sachen sind mir wirklich noch nicht ganz klar, aber das heißt nicht das ich darüber nichts lesen/lernen muss. Da stimme ich dir völlig zu. C kann schon ganz schön anstrengend sein mit der Speicherverwaltung, zuweisen von Strukturen, Arrayverwaltung usw. weshalb ich die großen Programme lieber mit Delphi schreibe. Da kommt es auch nicht auf jedes Byte - wie in diesem Fall an 😃

> [@symbiont](#):
>
> …und wenn du ein einen teil als bitfeld verwendest der vielleicht 16, oder 32, od 64 bit beansprucht dann nimmst halt den entsprechenden int61, 32, 64…

Ja dann müsste ich davon 30 Bits einzeln ablegen und die anderen in 2 bit oder 3 bit. Dabei bin ich mir nicht sicher, ob das wirklich effizienter ist. Zum Schluss müsste ich diese 30 einzelnen Bits als einzelne Felder auslesen, was das ganze nicht beschleunigt. Oder lieg ich da daneben?

---

<div class="post-metadata">

### Author: ![symbiont](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/s/ea666f/32.png) [@symbiont](https://www.pg-forum.de/u/symbiont)
#### Post date: [15. September 2009 um 06:55 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/14 "2009-09-15T06:55:29Z")

</div>

> [@hronny](#):
>
> Ja dann müsste ich davon 30 Bits einzeln ablegen und die anderen in 2 bit oder 3 bit.

musst du das? lassen die sich nicht in sinnvolle gruppen zusammenfassen?

bla\_flags INT16,  
blubb\_flags INT32,  
foo\_flags BYTE,  
bar\_flags INT64

oder sowas

---

<div class="post-metadata">

### Author: ![ads](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/8e7dd6/32.png) [@ads](https://www.pg-forum.de/u/ads)
#### Post date: [15. September 2009 um 07:15 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/15 "2009-09-15T07:15:07Z")

</div>

Für das TEXT-Feld werden einmalig 4 Bytes in der eigentlichen Tabelle verwendet und zusätzlich ein Eintrag variabler (also hier maximal 30 Bytes) Länge in der TOAST-Tabelle.

Für die verschiedenen Spalten sind diverse Einträge in der Haupttabelle notwendig.

Ich sehe hier keinen Vorteil.

---

<div class="post-metadata">

### Author: ![akretschmer](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/a6a055/32.png) [@akretschmer](https://www.pg-forum.de/u/akretschmer)
#### Post date: [15. September 2009 um 07:22 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/16 "2009-09-15T07:22:41Z")

</div>

> [@ads](#):
>
> Für das TEXT-Feld werden einmalig 4 Bytes in der eigentlichen Tabelle verwendet und zusätzlich ein Eintrag variabler (also hier maximal 30 Bytes) Länge in der TOAST-Tabelle.

```plaintext
The TOAST code is triggered only when a row value to be stored in a table is wider than TOAST_TUPLE_THRESHOLD bytes (normally 2 kB).

```

> Ich sehe hier keinen Vorteil.

Und ich kein Toastbrot 😉

Andreas

---

<div class="post-metadata">

### Author: ![symbiont](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/s/ea666f/32.png) [@symbiont](https://www.pg-forum.de/u/symbiont)
#### Post date: [15. September 2009 um 07:28 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/17 "2009-09-15T07:28:31Z")

</div>

> [@ads](#):
>
> Für das TEXT-Feld

welches TEXT-feld?

> [@ads](#):
>
> Ich sehe hier keinen Vorteil.

kein Wunder, solange Du TEXT-Felder siehst 🙂

[edit]

ach so du beziehst dich auf eine andere variante mit TEXT … na meinetwegen … ich habe mir wie so oft die freiheit genommen einfach zu schreiben, was mir dazu einfaellt …

aber wenn du moechtest - du bekommst ein bienchen - fuer besonders tolle TEXT-Felder

[edit2]

der vorteil in der variante mit den komponenten basiert ja nur auf der vermutung, dass seine flags sich sinnvoll gruppieren lassen … gerade mit seinen bit-operationen laesst es sich doch viel leichter arbeiten, wenn man bei einfachen datentypen bleibt … hat PG nicht selbst auch funktionen und operatoren fuer so kram? … vielleicht liegt dort der “vorteil” … naja … egal

---

<div class="post-metadata">

### Author: ![ads](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/8e7dd6/32.png) [@ads](https://www.pg-forum.de/u/ads)
#### Post date: [15. September 2009 um 09:10 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/18 "2009-09-15T09:10:39Z")

</div>

Nun ja, mein Fehler. Für Bytea gilt aber das gleiche. Ist auch ein Feld dynamischer Länge und wird in die TOAST-Tabelle ausgelagert.

---

<div class="post-metadata">

### Author: ![symbiont](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/s/ea666f/32.png) [@symbiont](https://www.pg-forum.de/u/symbiont)
#### Post date: [15. September 2009 um 09:27 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/19 "2009-09-15T09:27:22Z")

</div>

solche dinge kamen mir in den sinn:

```nohighlight
select (blubb_flags & 2)::boolean from ...

```

```nohighlight
select .. from ... where (blubb_flags & 2)::boolean

```

z.B. um zu schauen ob das 2. bit gesetzt ist … da kann man das auch gleich die DB erledigen lassen … oder manipulation usw.

```nohighlight
update ... set blubb_flags = blubb_flags # 2 ...

```

XOR 2. bit

ja PG macht manchmal spass 🙂

---

<div class="post-metadata">

### Author: ![hronny](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/h/8e8cbc/32.png) [@hronny](https://www.pg-forum.de/u/hronny)
#### Post date: [15. September 2009 um 18:48 UTC](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592/20 "2009-09-15T18:48:13Z")

</div>

_ **komme-aus-dem-Staunen-nicht-mehr-raus** _ 😲

Das mit den Bitoperatoren unter Postgresql kannte ich wirklich noch nicht. Wenn das schneller geht, könnte ich meine 3 “Gruppierfelder” evtl damit machen, es sind 2x jeweils 15 bits (4, 3 und 8). Zum Anzeigen, wenn ich mal schnell auf der Konsole was sehen möchte, müsste ich dann sicher eine Funktion schreiben, die mir beim SELECT das korrekt anzeigt/umwandelt. Alle anderen Daten werden im Client extern ausgewertet. Ich meine es stimmt schon, dass wenn ich es im Feldtyp “**character varying (8)**” speichere und der Wert im ungünstigsten Fall “15.7.254” ist, dann belegt es ja mindestens 8 Byte anstatt 2 für ein 16 bit Feld.

[Nächste Seite](https://www.pg-forum.de/t/bina-re-daten-von-max-30-bytes-einfa-gen/4592.md?page=2)
