1

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))
2
  • 1
    where name = excluded.name Commented Nov 9, 2018 at 16:47
  • For some reason, I'm still getting -- syntax error at or near ""users"" Commented Nov 9, 2018 at 16:54

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

I'm still getting the same error. I'll update my question with more code.
Concerning my object. I will be updating various tables based on value X existing and value Y being different. If value X doesn't exist then a new record will be added. Hopefully, I can accomplish that without posting another question.
This on conflict is only intended to solve the conflict. If you need to do more, like update various tables, you should use a before insert trigger.
Thanks for the info. I'm in the process of developing another question, because I still have an issue with my UPSERT.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.