2010-01-15 12 views
25

Gibt es eine Möglichkeit, einen Wert aus einem Array in pgSQL zu entfernen? Oder, um genauer zu sein, um den letzten Wert zu knacken? Gemessen an this list scheint die Antwort nein zu sein. Ich kann das gewünschte Ergebnis mit einem zusätzlichen Indexzeiger erhalten, aber es ist ein wenig umständlich.Array-Werte in pgSQL entfernen

Antwort

12

Nein, das glaube ich nicht. Zumindest nicht, etwas hässlich wie ohne das Schreiben:

SELECT ARRAY (
SELECT UNNEST(yourarray) LIMIT (
    SELECT array_upper(yourarray, 1) - 1 
) 
) 
+0

aus zu urteilen, was Google sagt mir, so scheint es, dass ich kippen.Ich werde dies als die akzeptierte Antwort markieren, es sei denn, jemand beweist, dass du falsch liegst :) – oggy

8

bin ich über Ihre Kontext nicht sicher, aber das sollte Ihnen etwas geben, mit zu arbeiten:

CREATE TABLE test (x INT[]); 
INSERT INTO test VALUES ('{1,2,3,4,5}'); 

SELECT x AS array_pre_pop, 
     x[array_lower(x,1) : array_upper(x,1)-1] AS array_post_pop, 
     x[array_upper(x,1)] AS popped_value 
FROM test; 


array_pre_pop | array_post_pop | popped_value 
---------------+----------------+-------------- 
{1,2,3,4,5} | {1,2,3,4}  |   5 
+0

Danke, das würde funktionieren, obwohl ich denke, dass das Schneiden nicht gerade eine effiziente Lösung ist? – oggy

+0

Ich denke, es ist deine beste Methode, da es keine eingebaute Funktion für pop() gibt. Ohne die Einzelheiten zu kennen, kann ich keinen besseren Rat geben. Wenn Sie die Inhalte für einen bestimmten Datensatz durchlaufen möchten, wäre "unnest()" wahrscheinlich besser, da es in eine Gruppe von Datensätzen konvertiert werden würde. Wenn Sie jedoch nur eine Tabelle aktualisieren möchten, um alle "letzten Elemente" des Arrays in mehreren Datensätzen zu entfernen, wäre Array-Slicing der richtige Weg. –

2

Ich habe so eine array_pop Funktion erstellt Sie können ein Element mit bekanntem Wert aus einem Array entfernen.

CREATE OR REPLACE FUNCTION array_pop(a anyarray, element character varying) 
RETURNS anyarray 
LANGUAGE plpgsql 
AS $function$ 
DECLARE 
    result a%TYPE; 
BEGIN 
SELECT ARRAY(
    SELECT b.e FROM (SELECT unnest(a)) AS b(e) WHERE b.e <> element) INTO result; 
RETURN result; 
END; 
$function$ 

gibt es auch eine Kern-Version https://gist.github.com/1392734

5

Hier ist eine Funktion, die ich für [] Arrays integer verwenden

CREATE OR REPLACE FUNCTION array_remove_item (array_in INTEGER[], item INTEGER) 
RETURNS INTEGER[] 
LANGUAGE SQL 
AS $$ 
SELECT ARRAY(
    SELECT DISTINCT $1[s.i] AS "foo" 
    FROM GENERATE_SERIES(ARRAY_LOWER($1,1), ARRAY_UPPER($1,1)) AS s(i) 
    WHERE $2 != $1[s.i] 
    ORDER BY foo 
); 
$$; 

Diese Integer Arrays offensichtlich für ist aber könnte für ANYARRAY ANYELEMENT

modifiziert werden
=> select array_remove_item(array[1,2,3,4,5], 3); 
-[ RECORD 1 ]-----+---------- 
array_remove_item | {1,2,4,5} 
14

Die einfachste Möglichkeit, den letzten Wert zu entfernen:

array1 = array[1,2,3] 
array1 = (select array1[1:array_upper(array1, 1) - 1]) 
+2

Dies sollte die akzeptierte Antwort sein. – Lucian

+0

Ja, das ist die Antwort - funktioniert gut mit einigen Semikolon. – Vidar

9

Es gibt einen einfachen Weg, um einen Wert aus einem Array in PLAIN SQL zu entfernen:

SELECT unnest('{5,NULL,6}'::INT[]) EXCEPT SELECT NULL 

es werden alle NULL-Werte aus dem Array entfernen. Ergebnis wird sein:

#| integer | 
------------ 
1| 5 | 
2| 6 | 
+0

Benutzer von Version 9.3+ sollten [diese Antwort] sehen (http://stackoverflow.com/a/27346920/3159183). Benutzer der Version 9.2 und niedriger können den obigen Code wie folgt zur Wiederverwendung einpacken: http://sqlfiddle.com/#!15/03d32/1/0 – SeldomNeedy

3

Ich laufe auf 9.2 und ich bin in der Lage dies auszuführen:

update tablename set arrcolumn=arrcolumn[1:array_length(arrcolumn)-1]; 

oder Sie können das Frontelement mit der gleichen Art von Sache verschieben off:

Vorsichtig, Programmierer - aus irgendeinem Grund noch unbekannt für die Wissenschaft, Pgsql-Arrays sind 1-indiziert statt 0-indiziert.

0

Versuchen Sie folgendes:

update table_name set column_name=column_name[1:array_upper(column_name, 1)-1]; 
-1

Meine Funktion für alle Arten von Arrays.

Außen Funktion:

CREATE OR REPLACE FUNCTION "outer_array"(anyarray, anyarray) RETURNS anyarray AS $$ 
    SELECT 
     "new"."item" 
    FROM (
     SELECT 
      ARRAY(
       SELECT 
        "arr"."value" 
       FROM (
        SELECT 
         generate_series(1, array_length($1, 1)) AS "i", 
         unnest($1)        AS "value" 
       ) "arr" 
       WHERE 
        "arr"."value" <> ALL ($2) 
       ORDER BY 
        "arr"."i" 
      ) AS "item" 
    ) "new" 
    $$ 
LANGUAGE sql 
IMMUTABLE 
RETURNS NULL ON NULL INPUT 
; 

Inner-Funktion:

CREATE OR REPLACE FUNCTION "inner_array"(anyarray, anyarray) RETURNS anyarray AS $$ 
    SELECT 
     "new"."item" 
    FROM (
     SELECT 
      ARRAY(
       SELECT 
        "arr"."value" 
       FROM (
        SELECT 
         generate_series(1, array_length($1, 1)) AS "i", 
         unnest($1)        AS "value" 
       ) "arr" 
       WHERE 
        "arr"."value" = ANY ($2) 
       ORDER BY 
        "arr"."i" 
      ) AS "item" 
    ) "new" 
$$ 
LANGUAGE sql 
IMMUTABLE 
RETURNS NULL ON NULL INPUT 
; 
55

In der Version 9.3 und höher können Sie tun:

update users set flags = array_remove(flags, 'active') 
+0

Ab 2015 ist dies die am besten geeignete Antwort - angenommen Sie " mindestens PostgreSQL 9.3. –

+0

Für diejenigen von euch, die noch nicht in der Lage waren, auf Version 9.3+ zu rollen, sollten Sie in der Lage sein, Ihre eigene 'array_remove()' wie gezeigt zu schreiben: http://sqlfiddle.com/#!15/03d32/1/0 – SeldomNeedy

+0

Dies ist absolut ** nicht ** "die am besten geeignete Antwort", da die Frage explizit fragt, ob wir den letzten Wert "knacken" können. Selbst wenn Sie zuerst nach dem Wert des letzten Elements fragen würden, würden, wenn dieser Wert überhaupt im Array wiederholt würde, ** alle ** Instanzen davon entfernt. Das ist offensichtlich nicht die gewünschte Funktionalität von etwas wie einer 'array_pop()' -Funktion, die das OP verlangt. – JMTyler