psycopg2 在“$body$”处或附近抛出未终止的美元引号字符串错误
psycopg2 throws unterminated dollar-quoted string error at or near "$body$"
我正在尝试构建一个 alembic 迁移修订版以在 PostgreSQL 服务器版本 10.2 中创建一个用户定义的函数,但是脚本不断抛出错误:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) unterminated dollar-quoted string at or near "$body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '"
LINE 6: as $body$
^
[SQL: "\n create or replace function naturalsort(text)\n returns bytea\n language sql\n immutable strict\n as $body$ \n select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '\x00') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r; \n $body$;\n "] (Background on this error at: http://sqlalche.me/e/f405)
我的剧本运行:
def upgrade():
conn = op.get_bind()
conn.execute('DROP FUNCTION IF EXISTS "naturalsort"')
conn.execute("""
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as $body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '\x00') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r;
$body$;
""")
该代码应允许对列进行自然排序,并且是 rhodium toad 的 copy/paste。
由于美元引号字符串是重写字符串常量的一种方式,替代方法是(请注意 postgresql 文档中的双单引号:"To include a single-quote character within a string constant, write two adjacent single quotes, e.g., 'Dianne''s horse'. Note that this is not the same as a double-quote character (")。” ):
conn.execute("""
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as 'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''\x00'') from regexp_matches(, ''0*([0-9]+)|([^0-9]+)'', ''g'') r;';
""")
但是这会引发类似的错误:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) unterminated quoted string at or near "'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''"
LINE 6: as 'select string_agg(convert_to(coalesce(r[2], leng...
^
[SQL: "\n create or replace function naturalsort(text)\n returns bytea\n language sql\n immutable strict\n as 'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''\x00'') from regexp_matches(, ''0*([0-9]+)|([^0-9]+)'', ''g'') r;';\n "] (Background on this error at: http://sqlalche.me/e/f405)
奇怪的是,这些查询在 pgAdmin 中执行得很好,而且 alembic 似乎生成了有效的 SQL(alembic 升级:--sql):
DROP FUNCTION IF EXISTS "naturalsort";
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as $body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r;
$body$;;
UPDATE alembic_version SET version_num='ad99fdcb28bc' WHERE alembic_version.version_num = 'ff00ac684617';
COMMIT;
关于为什么 psycopg2 不断抛出 unterminated dollar-quoted string at or near "$body$
错误的任何线索?
$body
是一个不能包含 $ 的别名,将 $body$
替换为 my_body
这样的名称,它应该可以工作
def upgrade():
op.execute('DROP FUNCTION IF EXISTS "naturalsort"')
op.execute("""
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as $my_body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r;
$my_body$;;
""")
def downgrade():
op.execute('DROP FUNCTION IF EXISTS "naturalsort"')
执行升级时,它成功了,没有语法错误。
实际上在 postgres 中执行该函数也会使用此查询返回所需的自然排序结果:
SELECT * FROM public.requirement ORDER BY naturalsort(eid) asc
使用 PvdL 关于 my_body
的评论部分起作用,如果我在空字符串现在所在的位置添加 '\x00'
(在 SQL_ASCII
之后),它将引发语法错误
我正在尝试构建一个 alembic 迁移修订版以在 PostgreSQL 服务器版本 10.2 中创建一个用户定义的函数,但是脚本不断抛出错误:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) unterminated dollar-quoted string at or near "$body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '"
LINE 6: as $body$
^
[SQL: "\n create or replace function naturalsort(text)\n returns bytea\n language sql\n immutable strict\n as $body$ \n select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '\x00') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r; \n $body$;\n "] (Background on this error at: http://sqlalche.me/e/f405)
我的剧本运行:
def upgrade():
conn = op.get_bind()
conn.execute('DROP FUNCTION IF EXISTS "naturalsort"')
conn.execute("""
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as $body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '\x00') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r;
$body$;
""")
该代码应允许对列进行自然排序,并且是 rhodium toad 的 copy/paste。
由于美元引号字符串是重写字符串常量的一种方式,替代方法是(请注意 postgresql 文档中的双单引号:"To include a single-quote character within a string constant, write two adjacent single quotes, e.g., 'Dianne''s horse'. Note that this is not the same as a double-quote character (")。” ):
conn.execute("""
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as 'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''\x00'') from regexp_matches(, ''0*([0-9]+)|([^0-9]+)'', ''g'') r;';
""")
但是这会引发类似的错误:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) unterminated quoted string at or near "'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''"
LINE 6: as 'select string_agg(convert_to(coalesce(r[2], leng...
^
[SQL: "\n create or replace function naturalsort(text)\n returns bytea\n language sql\n immutable strict\n as 'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''\x00'') from regexp_matches(, ''0*([0-9]+)|([^0-9]+)'', ''g'') r;';\n "] (Background on this error at: http://sqlalche.me/e/f405)
奇怪的是,这些查询在 pgAdmin 中执行得很好,而且 alembic 似乎生成了有效的 SQL(alembic 升级:--sql):
DROP FUNCTION IF EXISTS "naturalsort";
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as $body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r;
$body$;;
UPDATE alembic_version SET version_num='ad99fdcb28bc' WHERE alembic_version.version_num = 'ff00ac684617';
COMMIT;
关于为什么 psycopg2 不断抛出 unterminated dollar-quoted string at or near "$body$
错误的任何线索?
$body
是一个不能包含 $ 的别名,将 $body$
替换为 my_body
这样的名称,它应该可以工作
def upgrade():
op.execute('DROP FUNCTION IF EXISTS "naturalsort"')
op.execute("""
create or replace function naturalsort(text)
returns bytea
language sql
immutable strict
as $my_body$
select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '') from regexp_matches(, '0*([0-9]+)|([^0-9]+)', 'g') r;
$my_body$;;
""")
def downgrade():
op.execute('DROP FUNCTION IF EXISTS "naturalsort"')
执行升级时,它成功了,没有语法错误。 实际上在 postgres 中执行该函数也会使用此查询返回所需的自然排序结果:
SELECT * FROM public.requirement ORDER BY naturalsort(eid) asc
使用 PvdL 关于 my_body
的评论部分起作用,如果我在空字符串现在所在的位置添加 '\x00'
(在 SQL_ASCII
之后),它将引发语法错误