Синтаксическая ошибка UPSERT связана с UPDATE в PostgreSQL (python)

Я все еще изучаю PostgreSQL. Во время моего тестирования я использовал оператор INSERT только в psycopg2 и теперь asyncpg. Теперь у меня есть необходимость ОБНОВИТЬ данные в моей тестовой базе данных, а не заменять их все.

В настоящее время я пытаюсь выполнить простой тест замены в таблице тестирования, прежде чем перейти к таблице разработки с большим количеством данных.

Я хочу заменить любое имя в $1, находящееся в CONFLICT, на имя, которое уже есть в таблице users. Я пытаюсь код запроса, который передается в БД через asyncpg. Я продолжаю получать ошибки синтаксиса, поэтому я немного растерялся, как исправить эти ошибки.

Каков правильный синтаксис для этого запроса?

'''INSERT INTO users(name, dob) 
   VALUES($1, $2)
   ON CONFLICT (name)
   DO 
     UPDATE "users"
     SET name = 'TEST'
     WHERE name = excluded.name '''

ОБНОВИТЬ:

Я получаю это сообщение об ошибке при использовании asyncpg:

asyncpg.exceptions.PostgresSyntaxError: syntax error at or near ""users""

Я получаю это сообщение об ошибке при использовании psycopg2:

psycopg2.ProgrammingError: syntax error at or near ""users""

Это код asyncpg, который я использовал для вставки:

async def insert_new_records(self, sql_command, data):

    print (sql_command)

    async with asyncpg.create_pool(**DB_CONN_INFO, command_timeout=60) as pool:
        async with pool.acquire() as conn:
            try:
                stmt = await conn.prepare(sql_command)
                async with conn.transaction():
                    for value in data:
                        async for item in stmt.cursor(*value):
                            pass
            finally:
                await pool.release(conn)


test_sql_command = '''
INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
  UPDATE "users"
  SET name = 'TEST'
  WHERE name = excluded.name '''

# The name 'HELLO WORLD' exists in the table, but the other name does not.
params = [('HELLO WORLD', datetime.date(1984, 3, 1)),
          ('WORLD HELLO', datetime.date(1984, 3, 1))]

loop = asyncio.get_event_loop()
loop.run_until_complete(db.insert_new_records(test_sql_command, params))

2 ответа

Решение

Вам нужны одинарные кавычки вокруг значения имени: SET name='TEST'Двойные кавычки предназначены для имен таблиц или столбцов. В вашем случае вы можете просто удалить двойные кавычки вокруг users,

После редактирования: вы действительно должны попробовать свои команды SQL в консоли базы данных, это не имеет ничего общего ни с python, ни с async. Это чистый синтаксис postgresql.

Итак, вторая проблема в вашем запросе заключается в том, что вы не должны указывать "пользователей" после ОБНОВЛЕНИЯ. Подразумевается, что вы обновляете ту же таблицу. Так просто DO UPDATE SET... это хорошо.

Тогда вы получите column reference "name" is ambiguous, Ты должен написать DO UPDATE SET name='TEST', Вы уже обновляете строку where name=excluded.name, Я не на 100% понимаю, что вы пытаетесь сделать. Поэтому, если вы вставляете строку один раз, она вставляется как обычно. Если вы вставите его второй раз, имя будет заменено на "ТЕСТ". Исключенное ключевое слово позволяет получить доступ к попыткам вставки значений. Так, например, если вы хотите обновить last_access столбец при попытке вставить существующее имя, вы должны написать ON CONFLICT (name) DO UPDATE last_access=excluded.last_access,

Вы можете протестировать заменить: '''ВСТАВЬТЕ INTO пользователей (имя, доб) ЗНАЧЕНИЯ ($1, $2) В КОНФЛИКТЕ (имя) ОБНОВЛЯЙТЕ "пользователей" SET name = 'TEST' WHERE name = exclude.name' ''

by: "" "INSERT INTO users (name, dob) ЗНАЧЕНИЯ ($1, $2) ON CONFLICT (name) ОБНОВИТЬ ОБНОВЛЕНИЕ SET name = 'TEST' WHERE name = exclude.name """

Другие вопросы по тегам