What are the rules governing how a bind variable can be used in Postgres and where is this defined?
Posted
by
Craig Miles
on Stack Overflow
See other posts from Stack Overflow
or by Craig Miles
Published on 2013-10-18T03:24:05Z
Indexed on
2013/10/18
3:54 UTC
Read the original article
Hit count: 213
sql
|postgresql
I can have a table and function defined as:
CREATE TABLE mytable
(
mycol integer
);
INSERT INTO mytable VALUES (1);
CREATE OR REPLACE FUNCTION myfunction (l_myvar integer) RETURNS mytable AS $$
DECLARE
l_myrow mytable;
BEGIN
SELECT *
INTO l_myrow
FROM mytable
WHERE mycol = l_myvar;
RETURN l_myrow;
END;
$$ LANGUAGE plpgsql;
In this case l_myvar acts as a bind variable for the value passed when I call:
SELECT * FROM myfunction(1);
and returns the row where mycol = 1
If I redefine the function as:
CREATE OR REPLACE FUNCTION myfunction (l_myvar integer) RETURNS mytable AS $$
DECLARE
l_myrow mytable;
BEGIN
SELECT *
INTO l_myrow
FROM mytable
WHERE mycol IN (l_myvar);
RETURN l_myrow;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM myfunction(1);
still returns the row where mycol = 1
However, if I now change the function definition to allow me to pass an integer array and try to this array in the IN clause, I get an error:
CREATE OR REPLACE FUNCTION myfunction (l_myvar integer[]) RETURNS mytable AS $$
DECLARE
l_myrow mytable;
BEGIN
SELECT *
INTO l_myrow
FROM mytable
WHERE mycol IN (array_to_string(l_myvar, ','));
RETURN l_myrow;
END;
$$ LANGUAGE plpgsql;
Analysis reveals that although:
SELECT array_to_string(ARRAY[1, 2], ',');
returns 1,2 as expected
SELECT * FROM myfunction(ARRAY[1, 2]);
returns the error
operator does not exist: integer = text
at the line:
WHERE mycol IN (array_to_string(l_myvar, ','));
If I execute:
SELECT *
FROM mytable
WHERE mycol IN (1,2);
I get the expected result.
Given that array_to_string(l_myvar, ',') evaluates to 1,2 as shown, why arent these statements equivalent.
From the error message it is something to do with datatypes, but doesnt the IN(variable) construct appear to be behaving differently from the = variable construct?
What are the rules here?
I know that I could build a statement to EXECUTE, treating everything as a string, to achieve what I want to do, so I am not looking for that as a solution. I do want to understand though what is going on in this example. Is there a modification to this approach to make it work, the particular example being to pass in an array of values to build a dynamic IN clause without resorting to EXECUTE?
Thanks in advance
Craig
© Stack Overflow or respective owner