如何使用asyncpg API修复“ $ 1”或附近的“语法错误”

时间:2019-01-27 04:16:55

标签: python postgresql asyncpg

我正在尝试通过asyncpg API使用查询参数在Postgresql数据库的表中插入值。 我是这样创建表的:

CREATE TABLE my_table
(
    cat BIGINT,
    roles BIGINT ARRAY
);

我已经尝试过像这样直接在BIGINT中强制转换参数:$1:BIGINT,但出现相同的错误

await connection.execute('''
        INSERT INTO my_table(cat, roles)
        VALUES($1, $2)
        ON CONFLICT ($1)
        DO UPDATE SET roles = array_append(roles, $2)
        ''', cat, roles)

cat是一个int,作用是一个int数组

应该将cat和role插入my_table,但我刚得到错误:syntax error at or near "$1"

我提供数据库日志以防万一

2019-01-26 21:01:22 UTC:172.31.36.115(37598):Barbote@Barbotedb:[15082]:ERROR: syntax error at or near "$1" at character 111
2019-01-26 21:01:22 UTC:172.31.36.115(37598):Barbote@Barbotedb:[15082]:STATEMENT: 
INSERT INTO "429792212016955423"(cat, roles)
VALUES($1 $2)
ON CONFLICT ($1)
DO UPDATE SET roles = array_append(roles, $2);

1 个答案:

答案 0 :(得分:0)

您需要主键(或唯一列)才能使用ON CONFLICT,因此必须将表定义为

CREATE TABLE my_table
(
    cat BIGINT PRIMARY KEY, -- !!
    roles BIGINT ARRAY
);

roles中的列UPDATE不明确,请通过指定表名对其进行修复:

await connection.execute('''
        INSERT INTO my_table(cat, roles)
        VALUES($1, $2)
        ON CONFLICT (cat)
        DO UPDATE SET roles = array_cat(my_table.roles, $2)
        ''', cat, roles)

请注意,函数array_append()将元素添加到数组。您可以改用array_cat()。但是,这可能导致单个数组中的元素重复。如果您的目标是在数组中具有不同的元素,则应在Postgres中定义一个自定义函数:

create or replace function public.array_merge(anyarray, anyarray)
returns anyarray language sql
as $function$
    select 
        array(
            select unnest($1)
            union
            select unnest($2)
            order by unnest
        )
$function$;

并使用它代替array_cat()