Pavel Stehule recently wrote the post "Don't use SQL keywords as PLpgSQL variable names" describing the situation when internal stored routine variable names match PostgreSQL keywords.
But the problem is not only in keywords but also for plpgsql variable names. Consider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
CREATE TABLE human( name varchar, email varchar); CREATE FUNCTION get_user_by_mail(email varchar) RETURNS varchar LANGUAGE plpgsql AS $ DECLARE human varchar; BEGIN SELECT name FROM human WHERE email = email INTO human; RETURN human; END $; SELECT get_user_by_mail('foo@bar'); |
Output:
1 2 3 4 |
column reference 'email' is ambiguous LINE 1: SELECT name FROM human WHERE email = email ^ DETAIL: It could refer to either a PL/pgSQL variable or a table column. |
OK, at least we have no hidden error like in Pavel's case. Let's try to fix it specifying an alias for the table name:
1 2 3 4 5 6 7 8 9 10 |
CREATE FUNCTION get_user_by_mail(email varchar) RETURNS varchar LANGUAGE plpgsql AS $ DECLARE human varchar; BEGIN SELECT name FROM human u WHERE u.email = email INTO human; RETURN human; END $; |
Output:
1 2 3 4 |
column reference 'email' is ambiguous LINE 1: SELECT name FROM human u WHERE u.email = email ^ DETAIL: It could refer to either a PL/pgSQL variable or a table column. |
Seems better, but still parser cannot distinguish the variable name from column name. Of course, we may use variable placeholders instead of names. So, the quick dirty fix is like:
1 2 3 4 5 6 7 8 9 10 |
CREATE FUNCTION get_user_by_mail(email varchar) RETURNS varchar LANGUAGE plpgsql AS $ DECLARE human varchar; BEGIN SELECT name FROM human u WHERE u.email = $1 INTO human; RETURN human; END $; |
In addition, pay attention that human variable doesn't produce an error, even though it shares the same name with the target table. I personally do not like using $1 placeholders in code, so my suggestion would be (of course, if you don't want to change parameter name):
1 2 3 4 5 6 7 8 9 10 11 |
CREATE FUNCTION get_user_by_mail(email varchar) RETURNS varchar LANGUAGE plpgsql AS $ DECLARE human varchar; _email varchar = lower(email); BEGIN SELECT name FROM human u WHERE u.email = _email INTO human; RETURN human; END $; |
The same rules apply to plpgsql procedures.
To find out more about plpgsql procedures, see this blog post.
You need to load content from reCAPTCHA to submit the form. Please note that doing so will share data with third-party providers.
More InformationYou are currently viewing a placeholder content from Facebook. To access the actual content, click the button below. Please note that doing so will share data with third-party providers.
More InformationYou are currently viewing a placeholder content from X. To access the actual content, click the button below. Please note that doing so will share data with third-party providers.
More Information
Leave a Reply