Umlaute bei Regular Expressions

Hallo Fristo,
ich sehe neben den Betriebssystemen noch einen winzig kleinen Unterschied zwischen deiner und meiner Einstellung: Bei mir ist auch das client_encoding auf UTF-8 eingestellt. Klar, das sollte nun eigentlich wirklich gar nix ausmachen bei einem Server-internen Vergleich, aber …

Gruß,
Helmar

moin,

so jetzt schauts in der arbeit auch mal wieder etwas besser aus…

postgres=# SELECT ‘XXXMLLERYyyy’ ~* ‘.mller.’;
?column?

t
(1 row)

postgres=# SELECT UPPER(‘müller’);
upper

MüLLER
(1 row)

postgres läuft mit UTF-8, client ebenfalls.

cut b.

Hallo Xandrian,

uff! Jetzt wird es langsam unheimlich! Bei Fristo (Windows) läuft alles, bei mir (Linux) läuft zwar upper(), aber ~* geht nicht, und bei dir (ich glaub, es war Linux) geht noch nicht mal upper(). Mich würde - nur der Vollständigkeit halber - noch mal interessieren, was bei dir Fristos ~*-Vergleich als Wahrheitswert erbringt, wenn du den Umlaut mit einträgst.

Und: welche Postgres-Version verwendest du? Ich habe das Gefühl (auch wegen der Änderungs-Logs), dass die Postgres-Leute beim Übergang zu 8.1.1 irgendetwas im Umfeld Locale gemacht haben.

Gruß,
Helmar

ich kann doch auch nix dafür das des bei mir geht :wink:

hab jetzt nur phppgadmin bei der hand gehabt…

SELECT ‘XXXMLLERYyyy’ ~* ‘.müller.’;
Ergebnis: Faslch

ich verwende 8.1.1. selbst kompiliert ohne extras nur mit ssl auf einem unbuntu linux server. datenbank läuft auf utf-8.

cu tb.

Dass das Falsch ist, ist ja richtig :wink:

Ich meinte

SELECT ‘XXXMÜLLERYyyy’ ~* ‘.müller.’;

Wenn DAS falsch ist, dann isses ein Fehler :wink:

Gruß,
Helmar

hi,

klar das es falsch ist. aber wenn ich kein ergebnis angebe weißt du ja net was raus kommt :wink:

der andere select ist auch falsch…

cu tb.

SELECT ‘XXXMÜLLERYyyy’ ~* ‘.müller.’;

so wie ich das verstanden habe, bitte korrigiert mich wenn ich daneben liege, hängt das mit den LC_CTYPE einstellungen von postgres zusammen ob es geht oder nicht…

wenn das auf c oder posfix steht übernimmt es die einstellungen vom betriebssystem… und wenn das falsch eingestellt ist… sowie bei mir…muss man die os einstellungen ändern, da man den lc_ctype nachträglich nicht mehr ändern kann, außer man macht nochmal nen initdb (worauf ich keine lust habe)…

ich nutz übrigens suse…

Crypi

Hallo zusammen,
wir scheinen hier über einen “richtigen” Postgres-Fehler zu diskutieren. Ich habe soeben unter SuSE-10.0-Linux ein ganz frisches Postgres (Version 8.1.2) von Hand kompiliert und installiert. Alle LOCALE-Einstellungen stehen (und standen) auf de_DE.UTF-8.

Die SQL-Funktionen upper() und lower() arbeiteten so, wie man es erwartet, auch mit Umlauten. Der ~*-Test von Fristo führte zu einem falschen Wahrheitswert und funktionierte somit nicht.

Danach habe ich im Quellcode nachgesehen (src/backend/regex/regc_locale.c). Auch in dieser - neuesten - Version werden die C-Funktionen toupper(unsigned char) und tolower(unsigned char) verwendet, was meiner Meinung nach an dieser Stelle nicht richtig ist.

Wird der Funktionskörper von pg_wc_toupper ersetzt durch die Zeile
return towupper©;
bzw. der Funktionskörper von pg_wc_tolower durch die Zeile
return towlower©;

liefert Fristos Test nach einer Neukompilierung von Postgres die richtigen (und erwarteten) Ergebnisse.

Ergo: Zumindest für Linux gibt es offenbar einen Bug bei den Regular Expressions. Ich gehe aber davon aus, dass meine Korrekturvorschläge nur einen Teilaspekt der notwendigen Änderungen sind (ein Stückchen weiter oben stehen noch eine ganze Menge weiterer Funktionen, die zur ctype-Gruppe gehören und die dann sicher auch ausgetauscht werden müssten.

Daher werde ich nachher einen entsprechenden Bug-Report an postgresql.org abschicken.

Schöne Grüße,
Helmar

Hallo helmar,

kannst Du mit Deinem Bug-Report noch bis Anfang nächster Woche warten?

Ich habe heute morgen meine Applikation, die auf einer Datenbank mit Kodierung latin1 lief, auf der Datenbank mit der Kodierung UTF-8 gestartet und eine Fehlermeldung bekommen. Die Fehlermeldung hatte auch etwas mit Zeichenkonvertierung zu tun.

Eine Fehlermeldung hatte ich nicht erwartet, da die Datenbank externe Daten importiert, einen Auswertung macht und die Daten wieder exportiert. Die Fehlermeldung ist beim Exportieren der Daten aufgetreten! Die Untersuchung dauert etwas länger!


mfg

fristo

Hallo Fristo,
sorry, der Bugreport ist schon weg :frowning:

Und zu deiner Fehlermeldung: Ähnliches kenne ich auch aus der Zeit, als wir von Latin-1 auf UTF-8 umgestellt hatten. Ich gehe mal davon aus, dass du dem Server gesagt hast, dass dein Client auf Latin-1 läuft (set client_encoding to ‘latin1’). Dann hast du aber trotzdem Schwierigkeiten, wenn Zeichen an den Client weitergegeben werden sollen, die in Latin-1 nicht vorhanden sind (denke da z.B. an das Euro-Zeichen).

Aber was war denn das für eine Fehlermeldung im einzelnen?

Gruß,
Helmar

Hallo Crypi,

[quote=“Crypi”]SELECT ‘XXXMÜLLERYyyy’ ~* ‘.müller.’]

Eindeutig nein!



:!: Das nachfolgend geschriebene ist keine Garantie, das die beschriebenen Eigenschaften auch so in PostgreSQL z.Z. implemetiert sind. Der kleine Unterschied, zwischen Theorie und Praxis, zum besseren Verständnis! (Doku ist maßgebend) :!:

Locale definieren Sprachen und Formate.

PostgreSQL kennt derzeit die folgenden Locale: LC_MESSAGES, LC_MONETARY, LC_NUMERIC und LC_TIME.

LC_MESSAGES definiert die (Landes-) Sprache, in der Mitteilungen ausgegeben werden.
LC_MONETARY definiert die Formatierung von Geldbeträgen.
LC_NUMERIC definiert die Formatierung von Zahlen.
LC_TIME definiert die Formatierung von Datums- und Zeitwerten.

Diese Locale gelten für den Server und bedeuten bezüglich LC_MONETARY, LC_NUMERIC und LC_TIME, dass der Server beim Import von Daten, für die jeweils zugehörigen Daten-Typen, die definierten Formate erwartet und beim Export die entsprenden definierten Formate liefert.

Da die Locale von PostgreSQL in einer eigenen Datei stehen, sind sie unabhängig vom Betriebssystem. Rein theoretisch könnte man die Werte so definieren, dass die Mitteilungen in chinesisch ausgeben werden, die Formatierung von Datums- und Zeitwerten dem deutschem Format und die Formatierung von Zahlen dem US-Format entspricht.



Worüber wir hier reden ist Abhängigkeit vom Zeichensatz, den die Datenbank intern verwendet und mittels ‘encoding’ definiert wird. Dieser ist nicht zu verwechseln mit dem Zeichensatz des Clients, der mittels ‘client_encoding’ vorgegeben wird und in dem der Datentransfer zwischen Client und Server erfolgt. Sind der Zeichensatz von Client und Datenbank nicht gleich, so wird intern (Datenbank) eine Konvertierungs-Funktion aufgerufen. Siehe Convert-Funktion in der Doku.

Bei den Zeichensätzen muss man nun unterscheiden zwischen den Ein-Byte- und den Multi-Byte-Zeichensätzen. Ein Ein-Byte-Zeichensatz sind z.B. die Zeichensätze latin… . Der bekannteste Multi-Byte-Zeichensatz ist Unicode. Unicode verwendet für ein Zeichen zwische 1-4 Byte. Außer den ASCII-Zeichen (0x00 - 0x7F) haben alle andere Zeichen 2, 3 oder 4 Byte.

Wenn hier die Bezeichnung UTF-8 genannt wird, ist immer Unicode gemeint. UTF-8 selbst ist auch keine Zeichensatz sondern Kodierungsart für Unicode-Zeichen.



So, nun kanst Du dir mal Überlegen, warum ein Test mit “Miller” immer und mit “Müller” nicht immer funktioniert.



In der Table 21.1. “Server Character Sets” im englischen Manual kannst Du die notwendigen Bytes für die einzelnen Zeichensätze nachlesen.

Eine Beschreibung über die UTF-8 Kodierung kannst Du hier finden: http://de.wikipedia.org/wiki/UTF8.

Einen UTF Converter gibt es hier: http://www.macchiato.com/unicode/convert.html.

Und zu Zeichen-Tabellen habe ich hier auch noch ein Link: http://www.gymel.com/charsets



mfg

fristo

Hallo Crypi,

ich hab’ noch was vergessen.

So ein Funktionstest

SELECT 'XXXMÜLLERYyyy' ~* '.*müller.*';

schließt die Fehler bei den eigenen Daten aus. Den besten Beweis hast Du selbst geliefert:

[quote=“Crypi”]select upper(name) from kontakt]

Bei dem Ergebnis des Test’s upper(name) wo name = ‘müller’ würden bei mir die Alarmglocken :idea: :idea: :idea: schellen!


mfg

fristo

Hallo helmar,

war ein Fehlarlarm. Der Test ergab keinerlei Probleme.

Das einzige Zeichen welches unter Windows z.Z eine Sonderstellung hat ist das -Zeichen. Dieses hat den Code 0x7f. Wenn man beim Importieren die Konvertierung vergessen hat, ist das kein Datenverlust. Die Konvertierung kann man dann ja noch nachholen. Allerdings wird das -Zeichen ohne Konvertierung immer als Blank dargestellt.



mfg

fristo

Hey Leute,

Ich habe eine Datenbank mit Tel. Nummer.
Diese Nummern sehen z.B so aus: ‘0261/9372-0asdf’
jetzt will ich eine Abfrage machen, die nur die ziffern berücksichtig und alles andere nicht.
Ich suche jetzt z.B nach ‘02619372’ und will dass ich dann z.b das oben genannte Feld zuückgeliefert bekomme.
Kann mir da jemad helfen???

cu Manu

Könntest du für dein Problem einen eigenen Thread das nächste Mal aufmachen? :wink:

Im Normalfall ist dein Problem eine Aufgabe für die Normalisierung, wobei man die Daten gleich passend für die Suche aufbereiten und ablegen könnte. Ansonsten musst du wohl mit Text Ersetzungsfunktionen herangehen und alles herausschneiden, was dich interessiert.

http://www.postgresql.org/docs/8.2/interactive/functions-string.html

:confused: das mit dem eigenem Thread tut mir leid.

Dann gibt jemand die Tel. Nummer 6767-0 ein und ein anderer 67670.
Außerdem will ich die - und / zeichen in der Datenbank ja behalten.

Kennt vill jemand ne Funktion, so ähnlich wie btrin, nur umgekehr, also dass ich den ganzen satz lösche, außer das was ich eigentlich trim???
versteht ihr wie ich das meine???

Hast du auf die URL geschaut, die in meinem letzten Posting stand? Dort sind unter anderem Regexp Funktionen, die genau das realisieren können, was du möchtest.

Besonders schnell wird das allerdings nicht werden grübel

also substing hört sich eig ganz gut an, aber ich tscheck da nicht so ganz durch.
falls es nicht zu anstrengend währe, fände ich nen beispiel ganz nett :wink:

bei so einem datensatz ‘09879/089898-8’, wüsset ich jetzt nicht wie ich die ganzen zahlen ruasfiltern kann.

ach und das mit der schnelligkeit, iss imemrnoch besser alls alle anderen möglichkeiten.

substring() wird dich nicht weiterbringen, weil du damit nur Texte ausschneiden kannst, aber nicht weisst, welche Texte du genau herausschneiden musst.

test=# \timing
Timing is on.
test=# select regexp_replace('09879/089898-8', '[^0-9]', '', 'g');
 regexp_replace 
----------------
 098790898988
(1 row)

Time: 197.111 ms

Wie man sieht, hast du dein Ergebnis. Aber die Abfrage dauert, im Verhältnis gesehen, hier schon recht lange. Also erwarte nicht wirklich viel.

seufz Warum erledigen wir eigentlich die ganze Arbeit, während andere keine Zeit aufweisen, auch mal etwas zu lesen?

ohhh…großer meister ich danke Ihnen…
ja also so geht es. vielen vielen dank nochmal damit habe ich mir jetzt ne menge zeit gespart.

muss ganz ehrlich sagen, das dass mein erste post in irgendeinem forum ist, wo ich was frage. ich versuche schon immer, selber auf die lösungen zu kommen, oder freunde zu fragen, aber diesmal habe ich mich irgendwei verannt.