Синтаксическая ошибка PostgreSQL в параметризованном запросе на "дату $1"
Пытаясь параметризовать мои SQL-запросы (используя функцию libpq PQexecParams), я застрял в синтаксической ошибке:
SELECT date $1
Ошибка:
ERROR: syntax error at or near "$1"
2 ответа
Подготовленные заявления
Объяснение этому можно найти в главе Константы других типов руководства:
::
,CAST()
и синтаксисы вызова функций также могут использоваться для указания преобразований типов во время выполнения произвольных выражений, как обсуждалось в разделе 4.2.9. Чтобы избежать синтаксической неоднозначности,type 'string'
синтаксис может использоваться только для указания типа простой литеральной константы. Еще одно ограничение по типу'string' syntax
является то, что он не работает для типов массивов; использование::
или жеCAST()
указать тип константы массива.
Жирный акцент мой.
Параметры для подготовленных операторов на самом деле не строковые литералы, а типизированные значения, поэтому вы не можете использовать форму type 'string'
, Используйте одну из двух других форм, чтобы привести значение к другому типу, как вы уже нашли.
Пример:
PREPARE foo AS SELECT $1::date;
EXECUTE foo('2005-1-1');
Аналогично для PQexecParams
в библиотеке libpq C
Документация:
... В тексте команды SQL прикрепите явное приведение к символу параметра, чтобы показать, какой тип данных вы будете отправлять. Например:
SELECT * FROM mytable WHERE x = $1::bigint;
Это заставляет параметр
$1
рассматриваться какbigint
тогда как по умолчанию ему будет присвоен тот же тип, что и x. Настоятельно рекомендуется принудительно принять решение о типе параметра, либо таким образом, либо указав OID числового типа....
Альтернатива, как упомянуто в приведенной выше цитате, состоит в том, чтобы передавать OID соответствующих типов данных с paramTypes[]
- если вам действительно нужен актерский состав. В большинстве случаев все должно работать нормально, чтобы Postgres мог получать типы данных из контекста запроса.
paramTypes[]
Определяет по OID типы данных, которые должны быть назначены символам параметра. Если
paramTypes
являетсяNULL
или любой конкретный элемент в массиве равен нулю, сервер выводит тип данных для символа параметра так же, как и для нетипизированной литеральной строки.
Вы можете получить OID типов данных из системного каталога pg_type
:
SELECT oid FROM pg_type WHERE typname = 'date';
Вы должны использовать правильное имя внутреннего типа. Например: int4
за integer
,
Или с удобством, приведенным к regtype
:
SELECT 'date'::regtype::oid;
Это более гибко, так как также принимаются известные псевдонимы для имени типа. Например: int4
, int
или же integer
за integer
,
Решение состоит в том, чтобы использовать приведение типа вместо date
:
SELECT $1::date