There are the following table structures and data:
CREATE TABLE t_source_category (
id INT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
label varchar(255) NOT NULL,
path varchar(255) NOT NULL,
pid INT NOT NULL);
INSERT INTO t_source_category (id, label, path, pid) VALUES (1, 'New York State', '1', 0), (2, 'New York City', '1,2', 1), (3, 'Manhattan', '1,2,3', 2);
I want to run the following statement:
SELECT label FROM t_source_category WHERE id IN (SELECT STRING_TO_ARRAY(path, ',')::INT[] FROM t_source_category WHERE id = 3);
But it reported an error:
ERROR: operator does not exist: integer = integer[]
LINE 1: SELECT label FROM t_source_category WHERE id IN (SELECT STRI...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
I found a solution: use UNNEST
:
SELECT label FROM t_source_category WHERE id IN (SELECT UNNEST(STRING_TO_ARRAY(path, ',')::INT[]) FROM t_source_category WHERE id = 3);
then output:
label
---
New York State
New York City
Manhattan
What I am confused about is: WHERE IN
It should be followed by an array. Why does it say integer = integer[]
?
2
Answers
It is a syntax problem. There ate two forms of
IN
:expression IN (expression, expression, ...)
expression IN (SELECT ...)
The data types of these expressions has to be the same (or implicitly castable). That causes the error message you observe in your first attempt to use the second form.
The second form can also be written like this in standard SQL:
expression = ANY (SELECT ...)
PostgreSQL additionally offers another comparison:
expression = ANY (array expression)
and that’s the form that you should use if you already have an array.
IN
takes a list of values, not an array. The following query uses=ANY
to directly use an array from the subquery to produce the desired results (note, the cast toINT[]
is applied to the single row result):There appears to be a defect in PostgreSQL 16.3 (it might exist in other releases, but I haven’t tested them). The semantically equivalent query
results in the same exception as reported in the OP’s original post: