简体   繁体   中英

UPSERT syntax error linked to UPDATE in PostgreSQL (python)

I'm still learning PostgreSQL. During my testing, I have only been using INSERT statement in either psycopg2 and now asyncpg. I now have the need to UPDATE data in my test database, instead of replacing all of it.

I'm currently trying to do a simple replacement test in a testing table, before I move to development table with more data.

I want to replace any $1 name that is in CONFLICT with a name that is already in the table users. I'm trying the query code, which is passed to the DB via asyncpg. I keep getting a syntax errors, so I'm a little lost on how to correct these errors.

What is the proper syntax for this query?

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

UPDATE:

I'm getting this error message when using asyncpg:

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

I'm getting this error message when using psycopg2:

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

This is the asyncpg code that I have been using to do the INSERTs:

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))

You need single quotes around the value for name: SET name='TEST' The double quotes are for table or column names. In your case, you could just remove the double quotes around users .

After edit: You should really try your SQL commands in the database console, this has nothing to do with python nor async. It's pure postgresql syntax.

So, the second issue in your query is that you shouldn't specify "users" after UPDATE. It's implied that you're updating the same table. So just DO UPDATE SET... is good.

Then, you'll get column reference "name" is ambiguous . You should write DO UPDATE SET name='TEST' . You already are updating the row where name=excluded.name . I am not 100% clear on what you're trying to do. So if you insert a row once, it's inserted as usual. If you insert it a second time, the name is replaced with 'TEST'. The excluded keyword allows you to access the attempted insert values. So for example, if you wanted to update the last_access column when trying to insert an existing name, you would write ON CONFLICT (name) DO UPDATE last_access=excluded.last_access .

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM