3

I have a table if key - array pairs and need to check if a string is an element in a given array in this table. I have managed to write an if statement to check if the element is in an array but if I try to get the array from the table it does not work.

In the example below,
SELECT list FROM public."HelloWorldTable" WHERE name = 'HelloWorldList' selects the list element that contains an array that is identical to the one in the other if statement but I can not seem to access it the same.

MWE

CREATE TABLE IF NOT EXISTS "HelloWorldTable"(
 Name text PRIMARY KEY,
 List text[]
);
INSERT INTO public."HelloWorldTable" (name, list) VALUES ('HelloWorldList', ARRAY['Hello', 'World']);
DO $$
BEGIN 
 IF 'Hello' = ANY (ARRAY['Hello', 'World']::text[]) THEN
 RAISE NOTICE 'Found';
 ELSE
 RAISE NOTICE 'Not found';
 END IF;
-- failing attempt:
-- IF 'Hello' = ANY (SELECT list FROM public."HelloWorldTable"
-- WHERE name = 'HelloWorldList') THEN
-- RAISE NOTICE 'Found';
-- ELSE
-- RAISE NOTICE 'Not found';
-- END IF;
END $$;

I found this other question but I can not get it working the way I need it to. I have tried adding ::text and ::text[] to the second if statement but I only get different errors.
How can I solve this?

Erwin Brandstetter
186k28 gold badges463 silver badges636 bronze badges
asked Dec 10, 2019 at 15:09
5
  • Quote from the manual Arrays are not sets; searching for specific array elements can be a sign of database misdesign. Consider using a separate table with a row for each item that would be an array element. This will be easier to search, and is likely to scale better for a large number of elements Commented Dec 10, 2019 at 15:52
  • 1
    Unrelated to your question, but: you should really avoid those dreaded quoted identifiers. They are much more trouble than they are worth it. wiki.postgresql.org/wiki/… Commented Dec 10, 2019 at 15:52
  • It's a bit unclear to me what you are trying to achieve. Are you looking for a simple select * from helloworldtable where 'Hello' = any (list)? Commented Dec 10, 2019 at 15:54
  • 1
    If you really need to store key/value pairs, a jsonb column would be a much better choice (provided the de-normalization makes sense to begin with) Commented Dec 10, 2019 at 15:55
  • Note: I removed the redundant UNIQUE constraint, orthogonal to the problem. (And PK columns are NOT NULL automatically.) Commented Dec 11, 2019 at 18:52

1 Answer 1

2

Use instead:

DO $do$
BEGIN 
 IF EXISTS (
 SELECT FROM hello_world_table
 WHERE name = 'HelloWorldList'
 AND 'Hello' = ANY (list)
 ) THEN 
 RAISE NOTICE 'Found';
 ELSE
 RAISE NOTICE 'Not found';
 END IF;
END $do$;

db<>fiddle here

With a subselect between the parentheses, like you tried, the ANY construct expects a set of element types, not an array. That would work with the column list being type text, not text[].

I can see how this is confusing, as Postgres automatically extracts the single value from a single column in a returned set in most other contexts to match the expected form. Like:

SELECT '{Hello,World}' = (SELECT list FROM hello_world_table WHERE name = 'HelloWorldList');

The untyped string literal '{Hello,World}' is even cast to text[] automatically, deriving the type from the subselect on the other side.

But in this case, the ANY construct is resolved to its alternative form expecting a set, which makes your attempt fail.

You could make it work by unnesting the array to produce the expected set:

SELECT 'Hello' = ANY (SELECT unnest(list) FROM hello_world_table
 WHERE name = 'HelloWorldList');

But don't. Use an EXISTS subquery instead and move the condition to the WHERE clause like demonstrated.

Related:

answered Dec 11, 2019 at 18:24

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.