67

I'm getting a weird error when inserting some data from a Python script to MySQL. It's basically related to a variable being blank that I am inserting. I take it that MySQL does not like blank variables but is there something else I can change it to so it works with my insert statement?

I can successfully use an IF statement to turn it to 0 if its blank but this may mess up some of the data analytics I plan to do in MySQL later. Is there a way to convert it to NULL or something so MySQL accepts it but doesn't add anything?

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
Lostsoul
  • 25,013
  • 48
  • 144
  • 239
  • Does the column you're attempting to insert this NULL value into allow for NULLs? If not, what exactly is the error? – Philip Southam Apr 01 '11 at 00:26
  • yes it does allow for null. I see if I don't insert anything, it says the column is null the problem is my sql statements are constructed already. Basically I'm pulling a bunch of prices from a file, and sometimes the price is blank, it means no price is avail. I still want the details inserted but not the price. – Lostsoul Apr 01 '11 at 00:32
  • my first idea was to turn them all to zero, but it'll mess me up later on when I do some analytics and find free products shifting the average price of the products, etc.. – Lostsoul Apr 01 '11 at 00:32
  • What EXACTLY is the "weird error" that you are getting? What does "blank" mean? Do `print repr(socalled_blank_value)` and show us the answer. What is the SQL type of the corresponding column? – John Machin Apr 01 '11 at 03:18
  • sorry about that John. The error is "Data truncated for column 'price' at row 1 [SQLCode: 1265], [SQLState: 01000]" when I print the value of the variable its totally blank..i don't think there's a space in even because if i put "if variable == "":" that actually matches the value of this variable. – Lostsoul Apr 01 '11 at 03:21
  • @Lostsoul: **What does "blank" mean? Do print repr(socalled_blank_value) and show us the answer. What is the SQL type of the corresponding column?** – John Machin Apr 01 '11 at 03:25
  • Don't use zero, use a NULL and query on NOT NULL when doing you analytics. – Keith Apr 01 '11 at 06:14

6 Answers6

208

When using mysqldb and cursor.execute(), pass the value None, not "NULL":

value = None
cursor.execute("INSERT INTO table (`column1`) VALUES (%s)", (value,))

Found the answer here

SuperShoot
  • 9,880
  • 2
  • 38
  • 55
j c
  • 2,109
  • 1
  • 12
  • 6
  • 6
    it is an empty string in my case – barracuda317 Dec 10 '16 at 19:06
  • 1
    What if we don't use the %s notation? I usually use the "blah blah" + var + "blah blah" notation. – gunslingor Feb 22 '17 at 17:10
  • what if column1 is a number? – Kirby Apr 27 '17 at 04:34
  • I get the error `cannot concatenate 'str' and 'tuple' objects` if I use it. – Markus Feb 03 '18 at 19:52
  • 25
    For me this inserted None as a string and not NULL in the db – jht Dec 12 '18 at 06:28
  • beware that sure you are passing two parameters to execute. you ate not formatting string yourself. this worked for me with python 3.5. – nurp Jul 02 '19 at 07:17
  • It doesn't matter what datatype I've set for that column? you can still insert None to float column? – haneulkim Jul 29 '19 at 05:08
  • 2
    Wow, for some reason the comma next to the variable value like `(value,)` is important. I've been getting an error when trying to insert the same line of code except without the comma. – velociraptor11 Jan 08 '20 at 15:53
  • 4
    @velociraptor11 it’s because it needs a tuple. In python, if a tuple has only one elements, you must still use the comma (element,) or else the parenthesis will be evaluated as usual. (Element) becomes element once parenthesis are evaluated – MusicAndCode Oct 05 '20 at 21:09
1

Quick note about using parameters in SQL statements with Python. See the RealPython article on this topic - Preventing SQL Injection Attacks With Python. Here's another good article from TowardsDataScience.com - A Simple Approach To Templated SQL Queries In Python. These helped me with same None/NULL issue.

Also, I found that if I put "NULL" (without quotes) directly into the INSERT query in VALUES, it was interpreted appropriately in the SQL Server DB. The translation problem only exists if needing to conditionally add NULL or a value via string interpolation.

Examples:

cursor.execute("SELECT admin FROM users WHERE username = %s'", (username, ));

cursor.execute("SELECT admin FROM users WHERE username = %(username)s", {'username': username});

UPDATE: This StackOverflow discussion is more in line with what I'm trying to do and may help someone else.

Example:

import pypyodbc
myData = [
    (1, 'foo'),
    (2, None),
    (3, 'bar'),
]
connStr = """
DSN=myDb_SQLEXPRESS;
"""
cnxn = pypyodbc.connect(connStr)
crsr = cnxn.cursor()
sql = """
INSERT INTO myTable VALUES (?, ?)
"""
for dataRow in myData:
    print(dataRow)
    crsr.execute(sql, dataRow)
cnxn.commit()
crsr.close()
cnxn.close()
Ken Stulce
  • 23
  • 1
  • 5
0

if the col1 is char, col2 is int, a trick could be:

insert into table (col1, col2) values (%s, %s) % ("'{}'".format(val1) if val1 else "NULL", val2 if val2 else "NULL");

you do not need to add ' ' to %s, it could be processed before pass value to sql.

this method works when execute sql with session of sqlalchemy, for example session.execute(text(sql))

ps: sql is not tested yet

buxizhizhoum
  • 1,719
  • 1
  • 23
  • 32
-1

Based on above answers I wrote a wrapper function for my use case, you can try and change the function according to your need.

def sanitizeData(value):
    if value in ('', None):
        return "NULL"

    # This case handles the case where value already has ' in it (ex: O'Brien). This is how SQL skils single quotes
    if type(value) is str: 
        return "'{}'".format(value.replace("'", "''"))

    return value

Now call the sql query like so,

"INSERT INTO %s (Name, Email) VALUES (%s, %s)"%(table_name, sanitizeData(actual_name), sanitizeData(actual_email))
Yash Sharma
  • 169
  • 13
-3

Why not set the variable equal to some string like 'no price' and then filter this out later when you want to do math on the numbers?

filter(lambda x: x != 'no price',list_of_data_from_database)
Chris
  • 435
  • 5
  • 12
-26

Do a quick check for blank, and if it is, set it equal to NULL:

if(!variable_to_insert)
    variable_to_insert = "NULL"

...then make sure that the inserted variable is not in quotes for the insert statement, like:

insert = "INSERT INTO table (var) VALUES (%s)" % (variable_to_insert)
...

not like:

insert = "INSERT INTO table (var) VALUES ('%s')" % (variable_to_insert)
...
phaxian
  • 1,058
  • 16
  • 28
  • 1
    Thanks for the message, I thought of that but won't that just insert a variable with the text "NULL" in it? or is the text NULL a special character when inserting into databases? – Lostsoul Apr 01 '11 at 03:01
  • 1
    @Lostsoul: So perhaps you should show us the relevant part of your script. – John Machin Apr 01 '11 at 03:38
  • NULL is a special character when inserting into sql (without quotes). If you use the second insert, it would insert the string "NULL", bu the first will have a statement like: INSERT INTO table (var) VALUES (NULL) which will put a special NULL in for the value. – phaxian Apr 01 '11 at 04:43
  • 4
    @phaxian You shouldn't be inserting like this. You should be passing a string with parameters, and then a list of parameter values as a tuple. – Zenexer Sep 08 '13 at 07:09
  • 15
    This is really bad. You should be using parameters in your sql statements. Not using parameters leaves you open to sql injection attacks. – solarnz Sep 16 '13 at 05:12