BASE: Funktionen in Abfragen, Filename zerlegen

Hallo,

ich habe in einer BASE-Datenbank ein Feld FileName (nur der Name, ohne Pfad) und ich möchte den am letzten "." aufsplitten in Bezeichnung.Extension.

Zwar habe ich Beschreibungen einiger Funktionen <http://hsqldb.org/doc/2.0/guide/builtinfunctions-chapt.html#bfc_string_binary_functions> gefunden, aber INSTR und LOCATE führen zu Fehlermeldungen beim Ausführen der Abfrage. LOCATE läuft
/UPPER(RIGHT("FileName", 5- POSITION ('.' IN right("FileName", 5)))) AS "TYP"/
liefert aber nicht zuverlässig das richtige Ergebnis, da Werte wie

  * Text.EPUB,
  * 1.HTML
    aber auch
  * Version 1.0.DOC

vorkommen können.

Meine Fragen:

  * Gibt es eine Suche beginnend von rechts oder kann ich das z.B. mit
    Split und einem Array lösen?
  * Warum funktionieren einige Funktionen von der zitierten Seite nicht
    bzw. wo gibt es eine korrekte Übersicht?

LibreOffice Version: 6.1.5.2 / Build-ID: 90f8dcf33c87b3705e78202e3df5142b201bd805
Datenbank-Backend PostgreSQL 6.03 (die Abfrage möchte ich eigentlich in BASE bzw. final nur in dem entsprechenden Formular hinterlegen).

Danke, Michael

Hallo Michael,

ich habe in einer BASE-Datenbank ein Feld FileName (nur der Name, ohne
Pfad) und ich möchte den am letzten "." aufsplitten in
Bezeichnung.Extension.

Das geht nicht so einfach mit den eingebauten Funktionen, da eben die
Extension von der Länge her nicht festlegbar ist (ich finde bei
Wikipedia auch Erweiterungen mit 6 Zeichen ...) und eine Rückwärtssuche
für die eingebaute HSQLDB nicht existiert. Du kannst natürlich einen
String so lange begrenzen, bis in dem Ergebnis kein trennender Punkt
mehr vorhanden ist. So ähnlich funktioniert im Handbuch die "Suche mit
LOCATE".

Zwar habe ich Beschreibungen einiger Funktionen
<http://hsqldb.org/doc/2.0/guide/builtinfunctions-chapt.html#bfc_string_binary_functions>
gefunden, aber INSTR und LOCATE führen zu Fehlermeldungen beim Ausführen
der Abfrage. LOCATE läuft
/UPPER(RIGHT("FileName", 5- POSITION ('.' IN right("FileName", 5)))) AS
"TYP"/
liefert aber nicht zuverlässig das richtige Ergebnis, da Werte wie

* Text.EPUB,
 * 1.HTML
   aber auch
 * Version 1.0.DOC

vorkommen können.

Meine Fragen:

* Gibt es eine Suche beginnend von rechts oder kann ich das z.B. mit
   Split und einem Array lösen?

Nicht mit Hilfe von Abfragen und Funktionen in der eingebauten
Datenbank. Dazu müsstest Du gegebenenfalls Makros bemühen.

* Warum funktionieren einige Funktionen von der zitierten Seite nicht
   bzw. wo gibt es eine korrekte Übersicht?

Du suchst bei der falschen Version der HSQLDB. Die eingebaute Datenbank
ist die 1.8, nicht die 2.0. Alle für diese Datenbank verfügbaren
Funktionen sind auch im Handbuch beschrieben.

LibreOffice Version: 6.1.5.2 / Build-ID:
90f8dcf33c87b3705e78202e3df5142b201bd805
Datenbank-Backend PostgreSQL 6.03 (die Abfrage möchte ich eigentlich in
BASE bzw. final nur in dem entsprechenden Formular hinterlegen).

Wenn das Ganze unter PostgreSQL laufen soll, dann musst Du natürlich
dort in der Dokumentation nachsehen.

In MySQL gäbe es eine Funktion REVERSE(), mit der Du zuerst Deinen
String umdrehen könntest, dann darin den ersten Punkt suchen, an der
Stelle abschneiden und wieder zurückdrehen könntest. Diese Funktion ist
auch in der eingebauten Firebird-Datenbank verfügbar.

Gruß

Robert

Hallo Michael,

ich würde da lieber in der Datenbank zwei getrennte Felder für Bezeichnung und Extension führen; das dann als ein Feld mit dazwischenliegendem Punkt zu liefern, ist eine einfache Sache in einer View oder Abfrage.
Zum Füllen der neuen Spalten in der DB kannst du auf folgendem Code aufbauen:
Sub Main

dim arr(1) as string, ret as boolean

ret = lastDot("Version 1.0.DOC", arr)

if ret then
    msgbox arr(0) & " - " & arr(1)
  else
    msgbox "kein Punkt enthalten"
end if

End Sub

function lastDot(filename as string, arr() as string) as boolean

dim arrIntern() as variant, ub as integer

lastDot = FALSE
arrIntern = split(filename, ".")
ub = UBound(arrIntern)
if ub = 0 then exit function
arr(1) = arrIntern(ub)
Redim Preserve arrIntern(ub - 1)
arr(0) = Join(arrIntern, ".")
lastDot = TRUE

end function

Die Deklaration von arrIntern als varaint ist notwendig wegen *Bug 123025* <https://bugs.documentfoundation.org/show_bug.cgi?id=123025>.

Die Funktion könntest du auch verwenden, wenn du bei der Eingabe trotzdem ein einziges Feld haben willst, das dann zerlegt werden soll, bevor in die DB geschrieben wird.

Herzliche Grüße

Gerhard

Hallo Robert und Gerhard,

vielen Dank für die Vorschläge und Hinweise.

Zum Aufteilen des Dateinamen konnte ich mich nicht entschließen, die FUNCTION habe ich mir jedoch gemerkt; schade, dass man eine solche nicht in Abfragen nutzen kann.

Schließlich habe ich ähnlich dem Handbuch-Beispiel "Suche mit LOCATE" das Punkt-Finden und die Teilung verdoppelt:
SELECT DISTINCT "ID-Lit_fkey", "FileName",
CASE WHEN
   POSITION('.' IN RIGHT("FileName", 6 - POSITION('.' IN RIGHT("FileName", 6)))) > 0
   THEN
      UPPER (RIGHT("FileName", 6 - POSITION('.' IN RIGHT("FileName", 6))
                                 - POSITION('.' IN RIGHT("FileName", 6
                                 - POSITION('.' IN RIGHT("FileName", 6))))))
   ELSE
      UPPER (RIGHT("FileName", 6 - POSITION('.' IN RIGHT("FileName", 6))))
END
AS "Typ"
FROM "TabellenName" ;

Zumindest für meine aktuellen FileNamen funktioniert das, nicht elegant und wartungsfreundlich, aber immerhin.

Gruß, Michael