Remove array values in pgSQL
Is there a way to remove a value from 开发者_StackOverflow中文版an array in pgSQL? Or to be more precise, to pop the last value? Judging by this list the answer seems to be no. I can get the result I want with an additional index pointer, but it's a bit cumbersome.
In version 9.3 and above you can do:
update users set flags = array_remove(flags, 'active')
The simplest way to remove last value:
array1 = array[1,2,3]
array1 = ( select array1[1:array_upper(array1, 1) - 1] )
No, I don't think you can. At least not without writing something ugly like:
SELECT ARRAY (
SELECT UNNEST(yourarray) LIMIT (
SELECT array_upper(yourarray, 1) - 1
)
)
There IS a SIMPLE way to remove a value from an array in PLAIN SQL:
SELECT unnest('{5,NULL,6}'::INT[]) EXCEPT SELECT NULL
it will remove all NULL values from array. Result will be:
#| integer |
------------
1| 5 |
2| 6 |
I'm not sure about your context, but this should give you something to work with:
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
Here is a function I use for integer[] arrays
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
);
$$;
This is obviously for integer arrays but could be modified for ANYARRAY ANYELEMENT
=> select array_remove_item(array[1,2,3,4,5], 3);
-[ RECORD 1 ]-----+----------
array_remove_item | {1,2,4,5}
I'm running on 9.2 and I'm able to execute this:
update tablename set arrcolumn=arrcolumn[1:array_length(arrcolumn)-1];
or you can shift off the front element with the same kind of thing:
update tablename set arrcolumn=arrcolumn[2:array_length(arrcolumn)];
Careful, programmers -- for some reason still unknown to science, pgsql arrays are 1-indexed instead of 0-indexed.
I've created a array_pop function so you can remove an element with known value from an array.
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$
there is also a gist version https://gist.github.com/1392734
Try this:
update table_name set column_name=column_name[1:array_upper(column_name, 1)-1];
My function for all types of arrays.
Outer function:
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 function:
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
;
精彩评论