PostgreSQL syntax error in parameterized query on “date $1”

半城伤御伤魂 提交于 2019-12-02 05:14:09

Prepared statements

The explanation for this can be found in the chapter Constants of Other Types of the manual:

The ::, CAST(), and function-call syntaxes can also be used to specify run-time type conversions of arbitrary expressions, as discussed in Section 4.2.9. To avoid syntactic ambiguity, the type 'string' syntax can only be used to specify the type of a simple literal constant. Another restriction on the type 'string' syntax is that it does not work for array types; use :: or CAST() to specify the type of an array constant.

Bold emphasis mine.

Parameters for prepared statements are not actually sting literals but typed values, so you cannot use the form type 'string'. Use one of the other two forms to cast the value to a different type, like you found yourself already.

Example:

PREPARE foo AS SELECT $1::date;

EXECUTE foo('2005-1-1');

Similar for PQexecParams in the libpq C library

The documentation:

... In the SQL command text, attach an explicit cast to the parameter symbol to show what data type you will send. For example:

SELECT * FROM mytable WHERE x = $1::bigint;

This forces parameter $1 to be treated as bigint, whereas by default it would be assigned the same type as x. Forcing the parameter type decision, either this way or by specifying a numeric type OID, is strongly recommended. ...

The alternative, as mentioned in the quote above, is to pass the OIDs of respective data types with paramTypes[] - if you actually need the cast. In most cases it should work just fine to let Postgres derive data types from the query context.

paramTypes[]

Specifies, by OID, the data types to be assigned to the parameter symbols. If paramTypes is NULL, or any particular element in the array is zero, the server infers a data type for the parameter symbol in the same way it would do for an untyped literal string.

You can get the OID of data types from the system catalog pg_type:

SELECT oid FROM pg_type WHERE typname = 'date';

You must use the correct internal type name. For instance: int4 for integer.
Or with a convenience cast to regtype:

SELECT 'date'::regtype::oid;

This is more flexible as known aliases for the type name are accepted as well. For instance: int4, int or integer for integer.

The solution is to use a type cast instead of date:

SELECT $1::date
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!