How to insert nulls into a SQL Server table - python

I have the following dataframe:
data = [['Alex', 182.2],['Bob', 183.2],['Clarke', 188.4], ['Kelly', NA]]
df = pd.DataFrame(data, columns = ['Name', 'Height'])
I have the following SQL Server table:
create table dbo.heights as (
name varchar(10),
height float
)
This is my code to upload the data to my table:
for index,row in df.iterrows():
cursor.execute('INSERT INTO dbo.heights(name, height) values (?, ?)', row.name, row.height)
cnxn.commit()
cursor.close()
cnxn.close()
I want to upload the dataframe into my SQL Server table, but it fails on the null value. I tried replacing the NA with an np.nan value and it still failed. I also tried changing the height column to an "object" and replacing the NA with None and that also failed.

Please use the following instead:
for index, row in df.iterrows():
query = "INSERT INTO dbo.heights(name, height) values (?, ?)"
data = [row.name, row.height]
cursor.execute(query, data)
cursor.commit()
Or use the following:
query = "INSERT INTO dbo.heights(name, height) values (?, ?)"
data = [row.name, row.height for index, row in df.iterrows()]
cursor.executemany(query, data)
cursor.commit()
You'll see your None values as None in Python and as NULL in your database.

I tried replacing the NA with an np.nan
Because in such case you have to first define dataframe schema and make it nullable float.
"By default, SeriesSchema/Column objects assume that values are not nullable. In order to accept null values, you need to explicitly specify nullable=True, or else you’ll get an error."
Further Reading

Try like this
for index,row in df.iterrows():
cursor.execute("INSERT INTO table (`name`, `height`) VALUES (%s, %s)", (row.name, row.height))
cnxn.commit()
cursor.close()
cnxn.close()

Related

How do I update the column in postgresql python?

I am trying to add a new column in existing table and want to populate that column in database, there is a predictions column which is dataframe it is giving me error what I am doing wrong,
Code:
conn = create_connection()
cur = conn.cursor()
query = "ALTER TABLE STOCK_MARKET_FORECASTING ADD COLUMN predictions float"
cur.execute(query)
# Inserting predictions in database
def inserting_records(df):
for i in range(0 ,len(df)):
values = (df['Predicted_values_Hourly_Interval'][i])
cur.execute("UPDATE STOCK_MARKET_FORECASTING SET (predictions) VALUES (%s)", values)
conn.commit()
print("Records created successfully")
inserting_records(predictions)
You're passing in a single value – cur.execute requires a tuple of values.
You're probably looking for INSERT, not UPDATE. UPDATE updates existing rows.
def inserting_records(df):
series = df['Predicted_values_Hourly_Interval']
for val in series:
cur.execute("INSERT INTO STOCK_MARKET_FORECASTING (predictions) VALUES (%s)", (val, ))
conn.commit()
might be what you're looking for.

python sqlite3 parameterization - insert throws no such column error

Insert in columns with parameterized query throws no such column error
First (working) example:
# unit test input
name = "issue_number_1"
text = "issue_text"
rating_sum = 0
if name:
# check if issue is already in db
with self.conn: # this should release the connection when finished
test = cursor.execute("SELECT name, text FROM issue WHERE name = ?", (name,))
data = test.fetchall()
print(data)
this is working and prints:
[('issue_number_1', 'issue_text')]
Second (non working) example:
# unit test input
name = "issue_number_2"
text = "issue_text"
rating_sum = 0
if name:
with self.conn:
sql_string = "INSERT INTO issue (name, text, rating_sum) VALUES (name = ?, text = ?, rating_sum = ?)"
cursor.execute(sql_string, (name, text, rating_sum,))
throws this error:
cursor.execute(sql_string, (name, text, rating_sum,))
sqlite3.OperationalError: no such column: name
the column name exists, the first example proofed that
the name: "issue_number_2" does not exist in the DB
the second example fails exactly same with only name to insert (only one parameter)
i had no problems inserting with string concatenation so the problem should be in my second example code somewhere
You need to add single quote.for example:
"INSERT INTO table (field) VALUES ('$1')"
add just values in second () and add single quote around string values.
After a lot of experiments i was a little bit confused....
This is the right syntax:
sql_string = "INSERT INTO issue (name, text, rating_sum) VALUES (?, ?, ?)"
cursor.execute(sql_string, (name, text, rating_sum,))
The statement:
INSERT INTO .... VALUES ....
is an SQL statement and the correct syntax is:
INSERT INTO tablename (col1, col2, ...) VALUES (expr1, expr2, ...)
where col1, col2, ... are columns of the table tablename and expr1, expr2, ... are expressions or literals that are evaluated and assigned to each of the columns col1, col2, ... respectively.
So the syntax that you use is not valid SQL syntax.
The assignment of the values is not performed inside VALUES(...).
The correct syntax to use in Python would be:
INSERT INTO issue (name, text, rating_sum) VALUES (?, ?, ?)

Insert nested arrays into sql from python

I have a list contains many lists in python.
my_list = [['city', 'state'], ['tampa', 'florida'], ['miami','florida']]
The nested list at index 0 contains the column headers, and rest of the nested lists contain corresponding values. How would I insert this into sql server using pyodbc or slqalchemy? I have been using pandas pd.to_sql and want to make this a process in pure python. Any help would be greatly appreciated.
expected output table would look like:
city |state
-------------
tampa|florida
miami|florida
Since the column names are coming from your list you have to build a query string to insert the values. Column names and table names can't be parameterised with placeholders (?).
import pyodbc
conn = pyodbc.connect(my_connection_string)
cursor = conn.cursor()
my_list = [['city', 'state'], ['tampa', 'florida'], ['miami','florida']]
columns = ','.join(my_list[0]) #String of column names
values = ','.join(['?'] * len(my_list[0])) #Placeholders for values
query = "INSERT INTO mytable({0}) VALUES ({1})".format(columns, values)
#Loop through rest of list, inserting data
for l in my_list[1:]:
cursor.execute(query, l)
conn.commit() #save changes
Update:
If you have a large number of records to insert you can do that in one go using executemany. Change the code like this:
columns = ','.join(my_list[0]) #String of column names
values = ','.join(['?'] * len(my_list[0])) #Placeholders for values
#Bulk insert
query = "INSERT INTO mytable({0}) VALUES ({1})".format(columns, values)
cursor.executemany(query, my_list[1:])
conn.commit() #save change
Assuming conn is already open connection to your database:
cursor = conn.cursor()
for row in my_list:
cursor.execute('INSERT INTO my_table (city, state) VALUES (?, ?)', row)
cursor.commit()
Since the columns value are are the first elemnts in the array, just do:
q ="""CREATE TABLE IF NOT EXISTS stud_data (`{col1}` VARCHAR(250),`{col2}` VARCHAR(250); """
sql_cmd = q.format(col1 = my_list[0][0],col2 = my_list[0][1])
mcursor.execute(sql)#Create the table with columns
Now to add the values to the table, do:
for i in range(1,len(my_list)-1):
sql = "INSERT IGNORE into test_table(city,state) VALUES (%s, %s)"
mycursor.execute(sql,my_list[i][0],my_list[i][1])
mycursor.commit()
print(mycursor.rowcount, "Record Inserted.")#Get count of rows after insertion

SQLITE3 - Put Data in columns with a loop

I am using SQLITE3.
In my SQL Table, I have a table of 50 columns, and I would like to put in each column each value of My_List, which has 50 elements.
Is there any way to code a loop in python to put my data in my table ? I tried to find it out but didn't get anything...
My current code for 3 variables instead of 50 is:
import sqlite3
conn = sqlite3.connect("testdatabase.db")
c.execute('''CREATE TABLE mytable (Column1 text, Column2 text, Column3,
text) ''')
c.execute('''INSERT INTO mytable (Column1, Column2, Column3) VALUES (?,
?, ?)''', (myliste[0], myliste[1], myliste[2])
conn.commit()
Thank you very much.
Lcs
I see what you are trying to do. You almost have it. What you have is writing one row of data. just put that into a loop and you can write the whole table:
import sqlite3
conn = sqlite3.connect("testdatabase.db")
conn.execute("CREATE TABLE mytable (Column1 text, Column2 text, Column3 text)")
mytable = [
('a', 'b', 'c'),
('d', 'e', 'f'),
]
for myliste in mytable:
conn.execute("""INSERT INTO
mytable (Column1, Column2, Column3)
VALUES (?, ?, ?)""",
myliste)
conn.commit()
Update
To create 50 columns, if you have a list of columns already, replace the variable columns below with your own:
conn = sqlite3.connect("testdatabase.db")
conn.execute('DROP TABLE IF EXISTS mytable')
# Create ['Column1', 'Column2', ..., 'Column50']
columns = ['Column%d' % n for n in range(1, 51)]
# Create 'Column1 TEXT, ... Column50 TEXT'
columns_declaration = ', '.join('%s TEXT' % c for c in columns)
conn.execute("CREATE TABLE mytable (%s)" % columns_declaration)
conn.commit()
I answered a similar questions in this post I recommended to create a csv file and then use a bulk insert instead of using insert into because row by row is really slow, and with this method you don't need to worry about the number of columns or rows. I did it for sql server but I am pretty sure it will work in sqlite.
In SQL, you can omit the named columns in INSERT INTO assuming every column is being appended and values include data for all columns aligned to same table order.
Then consider dynamically building the placeholders for paramterization:
placeholders = ', '.join(['?'] * 50)
c.execute('''INSERT INTO mytable VALUES ({})'''.format(placeholders), mylist)

Python sqlite3 - operationalerror near "2017"

I'm new to programming. I have dictionary called record, that receives various inputs like 'Color', 'Type' 'quantity',etc. Now I tried to add a Date column then insert into sqlite table running through the 'if loop' with the code below. But I get an "Operational error near 2017", ie near the date.
Can anyone help please? Thanks in advance
Date = str(datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d'))
record['Date'] = Date
column = [record['Color'], Date]
values = [record['quantity'], record['Date']]
column = ','.join(column)
if record['Type'] == 'T-Shirts' and record['Style'] == 'Soft':
stment = ("INSERT INTO xtrasmall (%s) values(?)" %column)
c.execute(stment, values)
conn.commit()
Updated
You can simplify the code as follows:
from datetime import datetime
date = datetime.now().date()
sql = "INSERT INTO xtrasmall (%s, Date) values (?, ?)" % record['Color']
c.execute(sql, (record['quantity'], date))
This substitutes the value of the selected color directly into the column names in the query string. Then the query is executed passing the quantity and date string as arguments. The date should automatically be converted to a string, but you could convert with str() if desired.
This does assume that the other colour columns have a default value (presumably 0), or permit null values.
Original answer
Because you are constructing the query with string interpolation (i.e. substituting %s for a string) your statement becomes something like this:
INSERT INTO xtrasmall (Red,2017-10-06) values(?)
which is not valid because 2017-10-06 is not a valid column name. Print out stment before executing it to see.
If you know what the column names are just specify them in the query:
values = ['Red', 2, Date]
c.execute("INSERT INTO xtrasmall (color, quantity, date) values (?, ?, ?)", values)
conn.commit()
You need to use a ? for each column that you are inserting.
It looks like you want to insert the dictionary using its keys and values. This can be done like this:
record = {'date':'2017-10-06', 'color': 'Red', 'quantity': 2}
columns = ','.join(record.keys())
placeholders = ','.join('?' * len(record.values()))
sql = 'INSERT INTO xtrasmall ({}) VALUES ({})'.format(columns, placeholders)
c.execute(sql, record.values())
This code will generate the parameterised SQL statement:
INSERT INTO xtrasmall (date,color,quantity) VALUES (?,?,?)
and then execute it using the dictionary's values as the parameters.

Categories