2010-01-15 15 views
25

C'è un modo per rimuovere un valore da un array in pgSQL? O per essere più precisi, per inserire l'ultimo valore? A giudicare dal this list la risposta sembra essere no. Posso ottenere il risultato desiderato con un puntatore indice aggiuntivo, ma è un po 'macchinoso.Rimuovere i valori dell'array in pgSQL

risposta

12

No, non penso che tu possa. Almeno non senza scrivere qualcosa di brutto come:

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

A giudicare da ciò che Google mi dice, sembra che io non si può.Segnalo come risposta accettata a meno che qualcuno non ti dia ragione :) – oggy

8

non sono sicuro circa il vostro contesto, ma questo dovrebbe darvi qualcosa su cui lavorare:

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

Grazie, funzionerebbe anche se immagino che l'affettatura non sia esattamente una soluzione efficiente? – oggy

+0

Penso che sia il metodo migliore considerando che non esiste una funzione incorporata per pop(). Senza conoscere le specifiche, non posso dare un consiglio migliore. Se si desidera eseguire il looping dei contenuti per un particolare record, allora unnest() sarebbe probabilmente migliore in quanto verrebbe convertito in un set di record. Tuttavia, se si desidera aggiornare una tabella per rimuovere tutti gli "ultimi elementi" della matrice in più record, l'allineamento dell'array sarebbe la strada da percorrere. –

2

ho creato una funzione array_pop così è possibile rimuovere un elemento con valore noto da una matrice.

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$ 

esiste anche una versione sostanza https://gist.github.com/1392734

5

Qui è una funzione che uso per interi [] array

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 
); 
$$; 

Questo è ovviamente per le matrici di interi ma potrebbe essere modificato per anyarray anyelement

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

Il modo più semplice per rimuovere l'ultimo valore:

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

Questa dovrebbe essere la risposta accettata. – Lucian

+0

Sì, questa è la risposta - funziona per me bene con alcuni punti e virgola. – Vidar

9

C'è un modo semplice per rimuovere un valore da una matrice in PLAIN SQL:

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

rimuoverà tutti i valori NULL dalla matrice. Il risultato sarà:

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

Gli utenti della versione 9.3+ dovrebbero vedere [questa risposta] (http://stackoverflow.com/a/27346920/3159183). Gli utenti della versione 9.2 e seguenti possono concludere il codice sopra per il riutilizzo come questo: http://sqlfiddle.com/#!15/03d32/1/0 – SeldomNeedy

3

Io corro su 9.2 e sono in grado di eseguire questo:

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

o si può spostare fuori l'elemento frontale con lo stesso tipo di cosa:

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

Attento, programmatori - per qualche motivo ancora sconosciuto alla scienza, gli array pgsql sono 1-indexed invece di 0-indexed.

0

Prova questo:

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

La mia funzione per tutti i tipi di array.

funzione esterno:

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 
; 

funzione interno:

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

Nella versione 9.3 e soprattutto si può fare:

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

A partire dal 2015, questa è la risposta più appropriata-- supponendo che tu sia " ri almeno con PostgreSQL 9.3. –

+0

Per quelli di voi che non sono ancora riusciti a passare alla versione 9.3+, dovreste essere in grado di scrivere il vostro 'array_remove()' come mostrato: http://sqlfiddle.com/#!15/03d32/1/0 – SeldomNeedy

+0

Questo è assolutamente ** non ** "la risposta più appropriata", poiché la domanda chiede esplicitamente se siamo in grado di "inserire l'ultimo valore". Anche se dovessi prima eseguire una query sul valore dell'ultimo elemento, se tale valore è stato ripetuto del tutto nella matrice, tutte le ** istanze di essa sarebbero state rimosse. Ovviamente questa non è la funzionalità desiderata di qualcosa come una funzione 'array_pop()', che è ciò che l'OP sta chiedendo. – JMTyler

Problemi correlati