How to insert a dictionary into Postgresql Table with Pscycopg2

Question:

How do I insert a python dictionary into a Postgresql2 table? I keep getting the following error, so my query is not formatted correctly:

Error syntax error at or near “To” LINE 1: INSERT INTO bill_summary VALUES(To designate the facility of…

import psycopg2
import json
import psycopg2.extras
import sys
with open('data.json', 'r') as f:
        data = json.load(f)
con = None
try:
    con = psycopg2.connect(database='sanctionsdb', user='dbuser') 
    cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cur.execute("CREATE TABLE bill_summary(title VARCHAR PRIMARY KEY, summary_text VARCHAR, action_date VARCHAR, action_desc VARCHAR)")
    for d in data:
        action_date = d['action-date']
        title = d['title']
        summary_text = d['summary-text']
        action_date = d['action-date']
        action_desc = d['action-desc']
        q = "INSERT INTO bill_summary VALUES(" +str(title)+str(summary_text)+str(action_date)+str(action_desc)+")"
        cur.execute(q)
    con.commit()

except psycopg2.DatabaseError, e:

    if con:
        con.rollback()

    print 'Error %s' % e    
    sys.exit(1)
finally:

    if con:
        con.close()
Asked By: Owais Arshad

||

Answers:

 q = "INSERT INTO bill_summary VALUES(" +str(title)+str(summary_text)+str(action_date)+str(action_desc)+")" 

You’re writing your query in a wrong way, by concatenating the values, they should rather be the comma-separated elements, like this:

q = "INSERT INTO bill_summary VALUES({0},{1},{2},{3})".format(str(title), str(summery_text), str(action_date),str(action_desc)) 

Since you’re not specifying the columns names, I already suppose they are in the same orders as you have written the value in your insert query. There are basically two way of writing insert query in postgresql. One is by specifying the columns names and their corresponding values like this:

INSERT INTO TABLE_NAME (column1, column2, column3,...columnN)
VALUES (value1, value2, value3,...valueN);

Another way is, You may not need to specify the column(s) name in the SQL query if you are adding values for all the columns of the table. However, make sure the order of the values is in the same order as the columns in the table. Which you have used in your query, like this:

INSERT INTO TABLE_NAME VALUES (value1,value2,value3,...valueN);
Answered By: user2906838

You should use the dictionary as the second parameter to cursor.execute(). See the example code after this statement in the documentation:

Named arguments are supported too using %(name)s placeholders in the query and specifying the values into a mapping.

So your code may be as simple as this:

with open('data.json', 'r') as f:
    data = json.load(f)
    
print(data)

""" above prints something like this:

{'title': 'the first action', 'summary-text': 'some summary', 'action-date': '2018-08-08', 'action-desc': 'action description'}

use the json keys as named parameters:
"""

cur = con.cursor()
q = "INSERT INTO bill_summary VALUES(%(title)s, %(summary-text)s, %(action-date)s, %(action-desc)s)"
cur.execute(q, data)
con.commit()

Note also this warning (from the same page of the documentation):

Warning: Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint.

Answered By: klin
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.