Syntax errors are quite common while coding.
But, things go for a toss when it results in website errors.
PostgreSQL error 42601 also occurs due to syntax errors in the database queries.
At Bobcares, we often get requests from PostgreSQL users to fix errors as part of our Server Management Services.
Today, let’s check PostgreSQL error in detail and see how our Support Engineers fix it for the customers.
What causes error 42601 in PostgreSQL?
PostgreSQL is an advanced database engine. It is popular for its extensive features and ability to handle complex database situations.
Applications like Instagram, Facebook, Apple, etc rely on the PostgreSQL database.
But what causes error 42601?
PostgreSQL error codes consist of five characters. The first two characters denote the class of errors. And the remaining three characters indicate a specific condition within that class.
Here, 42 in 42601 represent the class “Syntax Error or Access Rule Violation“.
In short, this error mainly occurs due to the syntax errors in the queries executed. A typical error shows up as:
Here, the syntax error has occurred in position 119 near the value “parents” in the query.
How we fix the error?
Now let’s see how our PostgreSQL engineers resolve this error efficiently.
Recently, one of our customers contacted us with this error. He tried to execute the following code,
CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text)
RETURNS TABLE (name text, rowcount integer) AS
$$
BEGIN
WITH m_ty_person AS (return query execute sql)
select name, count(*) from m_ty_person where name like '%a%' group by name
union
select name, count(*) from m_ty_person where gender = 1 group by name;
END
$$ LANGUAGE plpgsql;
But, this ended up in PostgreSQL error 42601. And he got the following error message,
ERROR: syntax error at or near "return"
LINE 5: WITH m_ty_person AS (return query execute sql)
Our PostgreSQL Engineers checked the issue and found out the syntax error. The statement in Line 5 was a mix of plain and dynamic SQL. In general, the PostgreSQL query should be either fully dynamic or plain. Therefore, we changed the code as,
RETURN QUERY EXECUTE '
WITH m_ty_person AS (' || sql || $x$)
SELECT name, count(*)::int FROM m_ty_person WHERE name LIKE '%a%' GROUP BY name
UNION
SELECT name, count(*)::int FROM m_ty_person WHERE gender = 1 GROUP BY name$x$;
This resolved the error 42601, and the code worked fine.
[Need more assistance to solve PostgreSQL error 42601?- We’ll help you.]
Conclusion
In short, PostgreSQL error 42601 occurs due to the syntax errors in the code. Today, in this write-up, we have discussed how our Support Engineers fixed this error for our customers.
PREVENT YOUR SERVER FROM CRASHING!
Never again lose customers to poor server speed! Let us help you.
Our server experts will monitor & maintain your server 24/7 so that it remains lightning fast and secure.
GET STARTED
var google_conversion_label = «owonCMyG5nEQ0aD71QM»;
Your function would work like this:
CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text)
RETURNS TABLE (name text, rowcount int)
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE '
WITH v_tb_person AS (' || sql || $x$)
SELECT name, count(*)::int FROM v_tb_person WHERE nome LIKE '%a%' GROUP BY name
UNION
SELECT name, count(*)::int FROM v_tb_person WHERE gender = 1 GROUP BY name$x$;
END
$func$;
Call:
SELECT * FROM prc_tst_bulk($$SELECT a AS name, b AS nome, c AS gender FROM tbl$$)
You cannot mix plain and dynamic SQL the way you tried to do it. The whole statement is either all dynamic or all plain SQL. So I am building one dynamic statement to make this work. You may be interested in the chapter about executing dynamic commands in the manual.
The aggregate function count()
returns bigint
, but you had rowcount
defined as integer
, so you need an explicit cast ::int
to make this work.
I use dollar quoting to avoid quoting hell.
However, is this supposed to be a honeypot for SQL injection attacks or are you seriously going to use it? For your very private and secure use, it might be ok-ish — though I wouldn’t even trust myself with a function like that. If there is any possible access for untrusted users, such a function is a loaded footgun. It’s impossible to make this secure.
Craig (a sworn enemy of SQL injection) might get a light stroke when he sees what you forged from his answer to your preceding question.
The query itself seems rather odd, btw. The two SELECT
terms might be merged into one. But that’s beside the point here.
07.02.17 — 17:24
После обновления сервера 1С:Предприятие с 8.2 на 8.3 при работе c программой выскакивает сообщение об ошибке (даже при тестировании базы):
Ошибка СУБД
42601:ERROR: syntax error at near «not»
LINE 1: create table if not exists _tmpRCT (TabID bytea not null pri…
Платформа 8.3.9.2170, PostgreSQL 9.0.3-3.1C(x64), лицензии софтовые
1 — 07.02.17 — 17:31
Выгрузку базы под 8.2, загрузку под 8.3 пробовали?
2 — 07.02.17 — 17:36
Нет. Базы на постгре висят уже, обновилась только платформа сервера.
3 — 07.02.17 — 17:38
(2) Так вроде бы ничего не мешает попробовать, поднимите 2 сервера 1с параллельно, если 8.2 не осталось уже.
4 — 07.02.17 — 17:54
с какого на какой релиз 1С был переход?
5 — 07.02.17 — 17:54
то, что прыгнули на самый последний — это конечно здорово, но с какого спрыгивал — не написал
6 — 07.02.17 — 18:04
Не исправили видимо. Мы переходили на 8.3.9.2033 — та же фигня была. Пришлось поставить 8.3.8.1747 — минимально нужный для Бухгалтерии 2.0. Все нормально завелось.
7 — 07.02.17 — 18:11
(0) 8.3.9.2170 не поддерживает работу с PostgreSQL 9.0.3-3.1C(x64), если вы используете сборку 1С. В документации это отражено. И наоборот, старые платформы 1С не поддерживают новые сборки PostgreSQL.
Теоретически вероятно можно собрать версию 9.0.3 для работы с платформой 8.3.9. Практически в этом нет смысла.
Выгрузка в dt на старой платформе и загрузка из dt на новой платформе с новым SQL сервером.
Несколько SQL серверов могут жить под одной ОС. Например по портам разнести. Или по интерфейсам.
8 — 07.02.17 — 18:14
(7) У нас стоит 9.4.2-1.1C, и это нам не помогло.
9 — 07.02.17 — 18:15
Последняя 1с-кая сборка от 17.06.15. Тогда 8.3.9, наверное, только в мыслях у разработчика была.
10 — 07.02.17 — 18:23
(9) Можно попробовать сборку от Postgres Professional, 9.4.10, или 9.5.5-9.6.1, для эксперимента.
https://postgrespro.ru/products/1c_build
11 — 07.02.17 — 18:44
(10) Видели. Пока решили не пробовать. Но спасибо за ссылку!
12 — 08.02.17 — 12:59
Решил не заморачиваться с исправлением, тем более, что снова слетели програмные лицензии, получили новые, снова слетели и началась с ними колбасня. 1с запросила логи, а без лицухи ничего не запустить.
Поэтому решил все снести к чертям и установить заново.
Спасибо ansh15 за наводку на 9.4.10, поставил сразу его, пока полет нормальный.
13 — 08.02.17 — 13:52
(7) если не секрет, ссыль можете дать, где в документации указано, что не работает, что-то не нашел
14 — 08.02.17 — 14:16
Вот тут вроде как подобная тема обсуждается:
http://postgresql.ru.net/node/214401
«В одном из ответов говориться, что до версии 9.1 операторы DELETE, UPDATE, INSERT не могут быть использованы в подзапросах.»
15 — 08.02.17 — 14:23
(10) Все-таки лучше начинать с 9.6.1, там патчи для 1С доработанные. Все равно разработчики говорят, что «экспериментальная» практически такая же боевая.
16 — 08.02.17 — 16:49
(13)Но у меня сейчас доступа к сайту ИТС нет. Забыли продлить.
Вот что написано в файле Osobennosti_reliza_9.4.2-1.1C.txt, который можно скачать там же где и сборку 9.4.2-1.1C Postgresql:
«Поддержка этой версии в 1С:Предприятии 8.3 реализована в версии 8.3.3 и старше.
Для использования PostgreSQL 9.4.2-1.1C с версиями 1С:Предприятия ниже 8.3.3 необходимо его собрать с установленым значением параметра integer_datetimes=off»
Вероятно что-то похожее есть и в документации на платформу.
Для старых версий платформы (более старые чем 8.3.3) нужно использовать старые версии PostgreSQL, если не ошибаюсь, 9.0 и более старые. Для новых платформ нужно использовать 9.2 и новее. Про 9.1 просто не помню.
ansh15
17 — 09.02.17 — 00:36
(15) Да, нормально работает, потестировал на ней наши базы, проблем не возникало.
I have a table address_all
and it is inherited by several address tables. address_history
inherits from parent table history_all
and keeps current address information. I am creating new table which inherits address_all
table and copies information from address_history
to new table.
My stored procedure is like this below. I am having some error when I call it. To better explain error I am using line number.
1 CREATE OR REPLACE FUNCTION somefunc()
2 RETURNS void AS
3 $BODY$
4 DECLARE
5 year_id INTEGER;
6 month_id INTEGER;
7 week_id INTEGER;
8 addresstablename text;
9 backupdays text;
10 BEGIN
11 week_id := EXTRACT(DAY FROM TIMESTAMP 'now()');
12 month_id := EXTRACT(MONTH FROM TIMESTAMP 'now()');
13 year_id := EXTRACT(YEAR FROM TIMESTAMP 'now()');
14 addresstablename := 'address_history_' || week_id || '_' || month_id || '_' || year_id;
15 backupdays:= date_trunc('hour',CURRENT_TIMESTAMP - interval '7 days');
16 EXECUTE 'create table ' || addresstablename || '() INHERITS (address_all)';
17 EXECUTE 'insert into ' || addresstablename || ' select * from address_history where address_timestamp >= ' || backupdays || ''; --AS timestamp without time zone);
18 END;
19 $BODY$
20 LANGUAGE 'plpgsql' VOLATILE;
When I run:
select somefunc()
I get this error:
ERROR: syntax error at or near "12"
LINE 1: ...story where address_timestamp >= 2012-07-31 12:00:00-0...
^
QUERY: insert into address_history_7_8_2012 select * from address_history where address_timestamp >= 2012-07-31 12:00:00-04
CONTEXT: PL/pgSQL function "somefunc" line 14 at EXECUTE statement
********** Error **********
ERROR: syntax error at or near "12"
SQL state: 42601
Context: PL/pgSQL function "somefunc" line 14 at EXECUTE statement
asked Aug 7, 2012 at 16:24
Try this largely simplified form:
CREATE OR REPLACE FUNCTION somefunc()
RETURNS void AS
$func$
DECLARE
addresstablename text := 'address_history_' || to_char(now(), 'FMDD_MM_YYYY');
BEGIN
EXECUTE
'CREATE TABLE ' || addresstablename || '() INHERITS (address_all)';
EXECUTE
'INSERT INTO ' || addresstablename || '
SELECT *
FROM address_history
WHERE address_timestamp >= $1'
USING date_trunc('hour', now() - interval '7 days');
END
$func$ LANGUAGE plpgsql;
Major points:
-
You can assign variables in plpgsql at declaration time. Simplifies code.
-
Use
to_char()
to format your date. Much simpler. -
now()
andCURRENT_TIMESTAMP
do the same. -
Don’t quote
'now()'
, usenow()
(without quotes) if you want the current timestamp. -
Use the
USING
clause withEXECUTE
, so you don’t have to convert thetimestamp
totext
and back — possibly running into quoting issues like you did. Faster, simpler, safer. -
In
LANGUAGE plpgsql
,plpgsql
is a keyword and should not be quoted. -
You may want to check if the table already exists with
CREATE TABLE IF NOT EXISTS
, available since PostgreSQL 9.1.
answered Aug 7, 2012 at 17:05
Erwin BrandstetterErwin Brandstetter
595k144 gold badges1056 silver badges1215 bronze badges
1
Apparently you need to quote backupdays, or it is not seen as a string from where to parse a timestamp.
answered Aug 7, 2012 at 16:27
LSerniLSerni
55.3k10 gold badges65 silver badges107 bronze badges
0
You’re building SQL using string manipulation so you have to properly quote everything just like in any other language. There are a few functions that you’ll want to know about:
quote_ident
: quote an identifier such as a table name.quote_literal
: quote a string to use as a string literal.quote_nullable
: asquote_literal
but properly handles NULLs as well.
Something like this will server you better:
EXECUTE 'create table ' || quote_ident(addresstablename) || ...
EXECUTE 'insert into ' || quote_ident(addresstablename) || ... || quote_literal(backupdays) ...
The quote_ident
calls aren’t necessary in your case but they’re a good habit.
answered Aug 7, 2012 at 17:07
mu is too shortmu is too short
425k70 gold badges829 silver badges795 bronze badges
5
Добрый вечер. Есть выражение:
$this->insertStmt = $this->connection->getPdo()->prepare("
INSERT INTO files (
real_name,
virtual_name,
album,
size,
resolution,
duration,
comment,
path,
user
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
");
Которое вызывается как обычно:
protected function doInsert(object $object)
{
$values = [
$object->getRealName(),
$object->getVirtualName(),
$object->getAlbum(),
$object->getSize(),
$object->getResolution(),
$object->getDuration(),
$object->getComment(),
$object->getPath(),
$object->getUser(),
];
$this->insertStmt->execute($values);
}
Примерное содержание $values:
array(9) {
[0]=> string(15) "BvrK9z6UPxY.jpg"
[1]=> string(16) "1265dde1c67abc1c"
[2]=> string(23) "По умолчанию"
[3]=> int(54973)
[4]=> string(7) "720x430"
[5]=> NULL
[6]=> string(0) ""
[7]=> string(108) "files/id5cd487313a93a/По умолчанию/2019-05-10/1265dde1c67abc1c.jpg"
[8]=> string(15) "id5cd487313a93a"
}
Сообщение ошибки:
Type: PDOException
Code: 42601
Message: SQLSTATE[42601]: Syntax error: 7 ОШИБКА: ошибка синтаксиса (примерное положение: "user") LINE 11: user ^
С точки зрения синтаксиса вроде все верно, много раз перепроверил, IDE ни на что не ругается. В чем трабл, господа?