ich hatte vor längerer Zeit eine Funktion geschrieben, um damit die Daten nach Key Value Paaren in der Datenbank zu durchsuchen. Das klappt auch wunderbar. Allerdings bekomme ich immer wieder Fehler, wenn das Array leer ist, da hier kein upperbound (array_upper) gefunden werden kann. Wie kann ich diese Zeilen in der Abfrage gezielt ausschließen, bzw. das in der Funktion abfangen.
If array is not null oder array_upper($1,1) > 1 bzw. array_upper($1,1) < 2 scheinen trotz leeren Arrays immer ein true zu liefern.
in der SQL abfrage “where tags not null” wird als Syntaxfehler angezeigt und nicht ausgeführt. Irgendwie bin ich ratlos.
Das ist in SQL recht konsequent gelöst: es wird der Sonderwert “NULL” geliefert.
Vielleicht findest Du hier etwas brauchbares?
SELECT id,
data,
array_upper(data,1) AS "au",
array_upper(data,1)<2 AS "<2",
array_upper(data,1)>2 AS ">2",
COALESCE (array_upper(data,1), 0) AS size,
COALESCE (array_upper(data,1), 0) < 2 AS "size<2",
COALESCE (array_upper(data,1), 0) > 2 AS "size>2",
data IS NOT NULL AS "not null"
FROM test;
id | data | au(1) | <2 | >2 | size | size<2 | size>2 | not null
----+---------+-------+----+----+------+--------+--------+----------
1 | | | | | 0 | t | f | f
2 | {} | | | | 0 | t | f | t
3 | {1} | 1 | t | f | 1 | t | f | t
4 | {1,2,3} | 3 | f | t | 3 | f | t | t
(4 Zeilen)
Vielen Dank Mr. Wolf. Die Zeile “size<2” funktioniert jetzt ohne Fehlermeldung.
Damit sieht die Funktion jetzt wie folgt aus:
CREATE OR REPLACE FUNCTION c_k_v(text[], text, text)
RETURNS boolean AS'
DECLARE
BEGIN
if COALESCE(array_upper($1,1),0)<2 THEN
Return false;
END IF;
FOR i IN 1..(array_upper($1,1)) LOOP
if ($1[i]=$2 and $1[i+1]=$3) Then
Return true;
END IF;
i:=i+1;
END LOOP;
Return false;
END;
' LANGUAGE plpgsql;
Bist Du sicher, dass Du “FOR i IN” kombinieren willst mit “i := i +1”? Ob das funktioniert, hängt von der Implementation des “FOR” ab und man kann sich nicht wirklich darauf verlassen.
Wenn Du Schrittweite von zwei haben willst, kannst Du vereinfachen:
CREATE OR REPLACE FUNCTION c_k_v(text[], text, text) RETURNS boolean AS'
DECLARE
BEGIN
FOR i IN 1..COALESCE (array_upper($1,1)-1, 0) BY 2 LOOP
IF ($1[i]=$2 AND $1[i+1]=$3) THEN
RETURN TRUE;
END IF;
END LOOP;
RETURN FALSE;
END;
' LANGUAGE plpgsql;
Die Anzahl der Zeilen ist in Sachsen absolut gleich. Nur die Bearbeitungszeit ist bei deiner Funktion 12 Sekunden geringer. Was natürlich sehr positiv ist.