Синтаксическая ошибка UPSERT, связанная с UPDATE в PostgreSQL (python) - PullRequest
0 голосов
/ 09 ноября 2018

Я все еще изучаю 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 '''

UPDATE:

Я получаю это сообщение об ошибке при использовании 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 ]

0 голосов
/ 24 ноября 2018

вы можете проверить заменить: '' 'INSERT INTO users (name, dob) ЦЕННОСТИ ($ 1, $ 2) ПО КОНФЛИКТУ (имя) ДЕЛАТЬ ОБНОВЛЕНИЕ "пользователей" SET name = 'TEST' ГДЕ имя = исключено.имя '' '

от: "" "INSERT INTO users (name, dob) ЦЕННОСТИ ($ 1, $ 2) ПО КОНФЛИКТУ (имя) ДЕЛАТЬ ОБНОВИТЬ SET name = 'TEST' ГДЕ имя = исключено.имя "" "

0 голосов
/ 09 ноября 2018

Вам нужны одинарные кавычки вокруг значения имени: 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.

...