62

Is there a good practice for entering NULL key values to a PostgreSQL database when a variable is None in Python?

Running this query:

mycursor.execute('INSERT INTO products (user_id, city_id, product_id, quantity, price) VALUES (%i, %i, %i, %i, %f)' %(user_id, city_id, product_id, quantity, price))

results in a a TypeError exception when user_id is None.

How can a NULL be inserted into the database when a value is None, using the psycopg2 driver?

2
  • Which DB-API adapter are you using? Commented Nov 20, 2010 at 6:23
  • by DB-API adapter I suppose you mean the db interface psycopg2. If not, can you be more specific?
    – xpanta
    Commented Nov 20, 2010 at 6:34

4 Answers 4

75

To insert null values to the database you have two options:

  1. omit that field from your INSERT statement, or
  2. use None

Also: To guard against SQL-injection you should not use normal string interpolation for your queries.

You should pass two (2) arguments to execute(), e.g.:

mycursor.execute("""INSERT INTO products 
                    (city_id, product_id, quantity, price) 
                    VALUES (%s, %s, %s, %s)""", 
                 (city_id, product_id, quantity, price))

Alternative #2:

user_id = None
mycursor.execute("""INSERT INTO products 
                    (user_id, city_id, product_id, quantity, price) 
                    VALUES (%s, %s, %s, %s, %s)""", 
                 (user_id, city_id, product_id, quantity, price))
5
  • Thank you. Can you point me somewhere so I can read why string interpolation in python may lead to sql-injection. This is very interesting and I haven't thought of that.
    – xpanta
    Commented Nov 20, 2010 at 7:17
  • 3
    You're welcome. This describes well what SQL injection attacks are: en.wikipedia.org/wiki/SQL_injection How does this relate to string interpolation?: Say you receive untrusted input to your program. That input could contain, for example, a DROP TABLE command. Commented Nov 20, 2010 at 7:29
  • 5
    I'm using None for the column value but get an error: ProgrammingError: column "none" does not exist LINE 1: ...01.00-ng20', report_date='2016-03-30', ec_enabled=None, ec_s... Here's the original query that's failing: UPDATE kw_daily_data_mart SET hostname='ctrlkey.com', users_licensed=7, licensed_users=10, sw_version='kw2016.01.00-ng20', report_date='2016-03-30', ec_enabled=None, ec_server_count=1, config_max_file_version=10, av_enabled=True, location_count=1, sso_enabled=False WHERE customer_id=127892 AND installation_id=3585 AND hostname='ctrlkey.com' RETURNING id Commented Mar 30, 2016 at 18:29
  • 4
    I am using None, too and I get the same error as @Varun. Same python package psycopg2, v2.6.2. Posgresql v9.6
    – Romulus
    Commented Nov 14, 2016 at 19:49
  • 1
    Solution also works with an update query. Thanks for sharing! Commented May 10, 2017 at 17:08
11

With the current psycopg, instead of None, use a variable set to 'NULL'.

variable = 'NULL'
insert_query = """insert into my_table values(date'{}',{},{})"""
format_query = insert_query.format('9999-12-31', variable, variable)
curr.execute(format_query)
conn.commit()

>> insert into my_table values(date'9999-12-31',NULL,NULL)
2
  • 2
    this works for psycopg2 2.8.4, solution with inserting None ends up with the value 'None' in the db, as least for postgres
    – bucky
    Commented Jan 22, 2020 at 14:49
  • 2
    If the field being inserted is a text field, using 'NULL', simply inserts those four characters. The answer above (use None) is the correct one. Commented Apr 5, 2020 at 19:33
3

Here is my solution:

text = 'INSERT INTO products (user_id, city_id, product_id, quantity, price) VALUES (%i, %i, %i, %i, %f)' %(user_id, city_id, product_id, quantity, price))

text = text.replace("nan", "null")

mycursor.execute(text)
0

A simpler approach which also is practical with high number of columns:

Let row be a list of values to be inserted that may contain None. To insert it into PostgreSQL we do as follows

values = ','.join(["'" + str(i) + "'" if i else 'NULL' for i in row])
cursor.execute('insert into myTable VALUES ({});'.format(values))
conn.commit()
1
  • 2
    Maybe off topic but, I could suggest not to insert to a table without specifying the column names.
    – quents
    Commented Jan 18, 2021 at 14:15

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.