Python to read data from database and rewrite it into another table

Question:

def store_locations(location):
    db= psycopg2.connect(database=DATABASE, user=USER, password=PASSWD, host=HOST, port=PORT)
    cursor = db.cursor()
    insert_query = "INSERT INTO account_locations2(location) VALUES (%s) ON CONFLICT (location) DO UPDATE SET location=EXCLUDED.location"
    cursor.execute(insert_query, (location))
    db.commit()
    cursor.close()
    db.close()
    return


def read_locations():
    db= psycopg2.connect(database=DATABASE, user=USER, password=PASSWD, host=HOST, port=PORT)
    cursor = db.cursor()
    cursor.execute("SELECT * FROM public_accounts")
    rows = cursor.fetchall()
    for row in rows:
        print(row[3])
        store_locations(row[3])
    db.commit()
    cursor.close()
    db.close()

read_locations()

I have tried to use Python to read a specific column of a table from my database. When I was just printing it, it was successful and showed the content that I want. But when I was trying to restore it to another table, it gives me an error:

IndexError                                Traceback (most recent call last)
<ipython-input-38-7012639773d6> in <module>()
 23     db.close()
 24 
---> 25 read_locations()

<ipython-input-38-7012639773d6> in read_locations()
 18         location=row[3]
 19         print(location)
---> 20         store_locations(location)
 21     db.commit()
 22     cursor.close()

<ipython-input-38-7012639773d6> in store_locations(location)
  3     cursor = db.cursor()
  4     insert_query = "INSERT INTO account_locations2(location) VALUES (%s) ON CONFLICT (location) DO UPDATE SET location=EXCLUDED.location"
----> 5     cursor.execute(insert_query, (location))
  6     db.commit()
  7     cursor.close()

IndexError: string index out of range
Asked By: Hanwen Guo

||

Answers:

The second parameter in cursor.execute() should be a tuple:

cursor.execute(insert_query, (location,))

Per the documentation:

  • For positional variables binding, the second argument must always be a sequence, even if it contains a single variable (remember that Python requires a comma to create a single element tuple)

Note however that you can do the same in a single query like this:

INSERT INTO account_locations2(location) 
SELECT location FROM public_accounts
ON CONFLICT (location) DO NOTHING
-- when there is a conflict on location
-- then this makes no sense:
-- UPDATE SET location = EXCLUDED.location
-- as both are the same
Answered By: klin