Add a check an a array column

Started by vdgover 13 years ago10 messagesgeneral
Jump to latest
#1vdg
vdg.encelade@gmail.com

Hello,

I have a column defined as

test bigint[]

I would like to add a constraint on this column: the values stored must be
between 0 and 1023 inclusive

I know how to add a constraint on a column which is not an array:

check (test < x'400'::bigint)

but i can't find the way to do that when there is an array of values

Any help ?

Thank you

vdg

#2Andreas Kretschmer
akretschmer@spamfence.net
In reply to: vdg (#1)
Re: Add a check an a array column

vdg <vdg.encelade@gmail.com> wrote:

Hello,

I have a column defined as

test bigint[]

I would like to add a constraint on this column: the values stored must be
between 0 and 1023 inclusive

I know how to add a constraint on a column which is not an array:

check (test < x'400'::bigint)

but i can't find the way to do that when there is an array of values

Why bigint for values between 0 and 1023?

Okay, i think something like this:

test=# create or replace function check_array(int[]) returns bool as $$declare i int; begin select into i max(unnest) from unnest($1); if i > 10 then return false; end if; return true; end$$ language plpgsql ;
CREATE FUNCTION
Time: 0,579 ms
test=*# create table a (i int[] check (check_array(i)));
CREATE TABLE
Time: 6,768 ms
test=*# insert into a values (array[1,2,3]);
INSERT 0 1
Time: 0,605 ms
test=*# insert into a values (array[1,2,30]);
ERROR: new row for relation "a" violates check constraint "a_i_check"

(only for values greater than 10, but i think you can see the wa...)

Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082�, E 13.56889�

#3Joel Hoffman
joel.hoffman@gmail.com
In reply to: Andreas Kretschmer (#2)
Re: Add a check an a array column

More concisely, you can compare directly against all values of the array:

# create table i (i int[] check (0 <= ALL(i) AND 1023 >= ALL(i)));
# insert into i values (ARRAY[0,1,2,3,1023]);
# insert into i values (ARRAY[0,1,2,3,-1]);
ERROR: new row for relation "i" violates check constraint "i_i_check"
# insert into i values (ARRAY[0,1,2,3,1024]);
ERROR: new row for relation "i" violates check constraint "i_i_check"

Joel

On Sat, Sep 8, 2012 at 8:31 AM, Andreas Kretschmer <
akretschmer@spamfence.net> wrote:

Show quoted text

test=# create or replace function check_array(int[]) returns bool as
$declare i int; begin select into i max(unnest) from unnest($1); if i > 10
then return false; end if; return true; end$ language plpgsql ;
CREATE FUNCTION
Time: 0,579 ms
test=*# create table a (i int[] check (check_array(i)));
CREATE TABLE
Time: 6,768 ms
test=*# insert into a values (array[1,2,3]);
INSERT 0 1
Time: 0,605 ms
test=*# insert into a values (array[1,2,30]);
ERROR: new row for relation "a" violates check constraint "a_i_check"

#4Andreas Kretschmer
akretschmer@spamfence.net
In reply to: Joel Hoffman (#3)
Re: Add a check an a array column

Joel Hoffman <joel.hoffman@gmail.com> wrote:

More concisely, you can compare directly against all values of the array:

# create table i (i int[] check (0 <= ALL(i) AND 1023 >= ALL(i)));
# insert into i values (ARRAY[0,1,2,3,1023]);
# insert into i values (ARRAY[0,1,2,3,-1]);
ERROR: new row for relation "i" violates check constraint "i_i_check"

Nice! Didn't know that with all()

Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082�, E 13.56889�

#5Bret Stern
bret_stern@machinemanagement.com
In reply to: Andreas Kretschmer (#4)
Re: Add a check an a array column

On Sat, 2012-09-08 at 21:24 +0200, Andreas Kretschmer wrote:

Joel Hoffman <joel.hoffman@gmail.com> wrote:

More concisely, you can compare directly against all values of the array:

# create table i (i int[] check (0 <= ALL(i) AND 1023 >= ALL(i)));
# insert into i values (ARRAY[0,1,2,3,1023]);
# insert into i values (ARRAY[0,1,2,3,-1]);
ERROR: new row for relation "i" violates check constraint "i_i_check"

Nice! Didn't know that with all()

A better place for validation is in the front-end, before
adding/attempting to add data to the db (my opinion).
Nice to see there are always other ways though.

Show quoted text

Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082°, E 13.56889°

#6vdg
vdg.encelade@gmail.com
In reply to: Bret Stern (#5)
Re: Add a check an a array column

Thanks for your help.

Before posting, I had tried something like

check ((ALL(i) >= 0) AND (ALL(i) <= 1024 )));

but i got syntax errors.
It seems the first ALL() was not recognized.

Could someone give me documentation hints on this behaviour ?

vdg

Show quoted text

On Saturday, 08 September 2012 13:18:25 Bret Stern wrote:

On Sat, 2012-09-08 at 21:24 +0200, Andreas Kretschmer wrote:

Joel Hoffman <joel.hoffman@gmail.com> wrote:

More concisely, you can compare directly against all values of the
array:

# create table i (i int[] check (0 <= ALL(i) AND 1023 >= ALL(i)));
# insert into i values (ARRAY[0,1,2,3,1023]);
# insert into i values (ARRAY[0,1,2,3,-1]);
ERROR: new row for relation "i" violates check constraint "i_i_check"

Nice! Didn't know that with all()

A better place for validation is in the front-end, before
adding/attempting to add data to the db (my opinion).
Nice to see there are always other ways though.

Andreas

#7Thomas Kellerer
spam_eater@gmx.net
In reply to: Bret Stern (#5)
Re: Add a check an a array column

Bret Stern wrote on 08.09.2012 22:18:

A better place for validation is in the front-end, before
adding/attempting to add data to the db (my opinion).
Nice to see there are always other ways though.

I beg to differ: every validation that can be enforced by declarative constraints *should* be checked there.

As a wise man once said: your application won't be the last one to use the data and it won't be the only one.
And most of the data that is of any interest lives a lot longer than the application(s).

Nowaday it's not uncommon that multiple applications read and write to the same database and in that case you simply
cannot rely on all of them to validate the data.

Thomas

#8Andreas Kretschmer
akretschmer@spamfence.net
In reply to: Thomas Kellerer (#7)
Re: Add a check an a array column

Thomas Kellerer <spam_eater@gmx.net> wrote:

Bret Stern wrote on 08.09.2012 22:18:

A better place for validation is in the front-end, before
adding/attempting to add data to the db (my opinion).
Nice to see there are always other ways though.

I beg to differ: every validation that can be enforced by declarative constraints *should* be checked there.

As a wise man once said: your application won't be the last one to use the data and it won't be the only one.
And most of the data that is of any interest lives a lot longer than the application(s).

Nowaday it's not uncommon that multiple applications read and write to the same database and in that case you simply
cannot rely on all of them to validate the data.

Full ack.

Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082�, E 13.56889�

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: vdg (#6)
Re: Add a check an a array column

vdg <vdg.encelade@gmail.com> writes:

Before posting, I had tried something like

check ((ALL(i) >= 0) AND (ALL(i) <= 1024 )));

but i got syntax errors.

Well, that's not the syntax.

Could someone give me documentation hints on this behaviour ?

http://www.postgresql.org/docs/9.1/static/functions-subquery.html#FUNCTIONS-SUBQUERY-ALL
http://www.postgresql.org/docs/9.1/static/functions-comparisons.html#AEN17447

regards, tom lane

#10Gavin Flower
GavinFlower@archidevsys.co.nz
In reply to: vdg (#6)
Re: Add a check an a array column

On 09/09/12 23:12, vdg wrote:

Thanks for your help.

Before posting, I had tried something like

check ((ALL(i) >= 0) AND (ALL(i) <= 1024 )));

but i got syntax errors.
It seems the first ALL() was not recognized.

Could someone give me documentation hints on this behaviour ?

vdg

On Saturday, 08 September 2012 13:18:25 Bret Stern wrote:

On Sat, 2012-09-08 at 21:24 +0200, Andreas Kretschmer wrote:

Joel Hoffman <joel.hoffman@gmail.com> wrote:

More concisely, you can compare directly against all values of the
array:

# create table i (i int[] check (0 <= ALL(i) AND 1023 >= ALL(i)));
# insert into i values (ARRAY[0,1,2,3,1023]);
# insert into i values (ARRAY[0,1,2,3,-1]);
ERROR: new row for relation "i" violates check constraint "i_i_check"

Nice! Didn't know that with all()

A better place for validation is in the front-end, before
adding/attempting to add data to the db (my opinion).
Nice to see there are always other ways though.

Andreas

I find rewriting examples a good way of understanding things, and as I
was not sure about the use of 'i' as both table name and field name I
rewrote the example given. I also gave it slightly more realistic names
and added a few extra fields. The rewritten example performs exactly as
the original for the purposes of the question.

My custom is to write SQL as a script and ten execute it, this allows me
to keep the example for later use, and to correct any mistakes I make.

I made no change in the _syntax_ of the check condition.

I hope this helps.

Cheers,
Gavin

DROP TABLE IF EXISTS tarcon;

CREATE TABLE tarcon
(
id serial PRIMARY KEY,
name text,
va int[] check (0 <= ALL(va) AND 1023 >= ALL(va)),
ok boolean
);

-- succeeds
INSERT INTO tarcon (va)
VALUES (ARRAY[0,1,2,3,1023]);

-- gives ERROR
INSERT INTO tarcon (va)
VALUES (ARRAY[0,1,2,3,-1]);