I have a python web scraper that scrapes an apartment website and compiles various pieces of information about each property. I'm trying to use SQLite to dynamically insert each variable from the scraper to the SQLite DB. So Far I have written this code and it successfully inserts 1 row. For this to work I need it to insert all the rows. Could this be solved with a for loop?
'''
conn = sqlite3.connect('RentScraper.db')
c = conn.cursor()
def create_table():
# Create table
c.execute("""CREATE TABLE IF NOT EXISTS property (\
property_name varchar (250) NOT NULL,\
street_address varchar (20) NOT NULL,\
rent_price varchar (20) NULL,\
available_units INT NULL,\
contact_number varchar(50) NULL,\
PRIMARY KEY (property_name))""")
def dynamic_data_entry():
c.execute("INSERT INTO property (property_name, street_address, rent_price, available_units, contact_number) VALUES (?, ?, ?, ?, ?)",
(name, city, price, units_avl, contact))
conn.commit()
create_table()
dynamic_data_entry()
'''
Related
Attempting to build a database, inserting from 33 CSV files, my insert statement returns:
ProgrammingError: Incorrect number of bindings supplied. The current statement uses 4, and there are 11 supplied.
I have a CSV file I need to convert a single column from into a string then insert that CSV file into a table. How to do this? I want to create a database I can run queries on after inserting CSV file data into its tables.
import sqlite3
import pandas as pd
from traceback import print_exc as pe
import csv
def Connect():
conn = sqlite3.connect('storefront.db')
curs = conn.cursor()
curs.execute("PRAGMA foreign_keys = ON;") #change back to on after finding errors
return conn, curs
def BuildTables():
conn, curs = Connect()
curs.execute("DROP TABLE IF EXISTS tState;")
curs.execute("DROP TABLE IF EXISTS tZip;")
curs.execute("DROP TABLE IF EXISTS tCust;")
curs.execute("DROP TABLE IF EXISTS tOrder;")
curs.execute("DROP TABLE IF EXISTS tOrderDetail;")
curs.execute("DROP TABLE IF EXISTS tProd;")
sql = """
CREATE TABLE tState(
st TEXT NOT NULL PRIMARY KEY,
state TEXT NOT NULL
);"""
curs.execute(sql)
file = open('data/states.csv')
contents = csv.reader(file)
insert_records = "INSERT INTO tState (st, state) VALUES(?, ?)"
curs.executemany(insert_records, contents)
sql = """
CREATE TABLE tZip(
zip TEXT NOT NULL PRIMARY KEY,
city TEXT NOT NULL,
st TEXT NOT NULL
);"""
curs.execute(sql)
sql = """
CREATE TABLE tCust(
cust_id int AUTO_INCREMENT PRIMARY KEY,
first TEXT NOT NULL,
last TEXT NOT NULL,
addr TEXT NOT NULL,
zip TEXT NOT NULL
);"""
curs.execute(sql)
file3 = open('data/Sales_201901.csv')
cont = csv.reader(file3)
cust = "INSERT INTO tCust (first, last, addr, zip) VALUES(?, ?, ?, ?)"
curs.executemany(cust, cont)
sql = """
CREATE TABLE tOrder(
order_id int AUTO_INCREMENT PRIMARY KEY,
date TEXT NOT NULL
);"""
curs.execute(sql)
order = "INSERT INTO tOrder (date) VALUES(?)"
curs.executemany(order, cont)
sql = """
CREATE TABLE tOrderDetail(
order_id INTEGER NOT NULL REFERENCES tOrder(order_id),
cust_id INTEGER NOT NULL REFERENCES tCust(cust_id),
qty TEXT,
PRIMARY KEY (order_id, cust_id)
);"""
curs.execute(sql)
orderdetails = "INSERT INTO tOrderDetail (qty) VALUES(?)"
curs.executemany(orderdetails, cont)
sql = """
CREATE TABLE tProd(
prod_id INTEGER NOT NULL PRIMARY KEY,
prod_name TEXT NOT NULL,
unit_price TEXT NOT NULL
);"""
curs.execute(sql)
file4 = open('data/prods.csv')
conts = csv.reader(file4)
prod = "INSERT INTO tProd (prod_id, prod_name, unit_price) VALUES (?, ?, ?)"
curs.executemany(prod, conts)
conn.close()
return True
import csv
import sqlite3
open("shows.db", "w").close()
con = sqlite3.connect('shows.db')
db = con.cursor()
db.execute("CREATE TABLE shows (id INTEGER, title TEXT, PRIMARY KEY(id))")
db.execute("CREATE TABLE genres (show_id INTEGER, genre TEXT, FOREIGN KEY(show_id) REFERENCES shows(id))")
with open("/Users/xxx/Downloads/CS50 2019 - Lecture 7 - Favorite TV Shows (Responses) - Form Responses 1.csv", "r") as file:
reader = csv.DictReader(file)
for row in reader:
title = row["title"].strip().upper()
id = db.execute("INSERT INTO shows (title) VALUES(?)", (title,))
for genre in row["genres"].split(", "):
db.execute("INSERT INTO genres (show_id, genre) VALUES(?, ?)", id,genre)
con.commit()
con.close()
When I run this code I think in this line "db.execute("INSERT INTO genres (show_id, genre) VALUES(?, ?)", id,genre)" the problem happens.
My console says
"db.execute("INSERT INTO genres (show_id, genre) VALUES(?, ?)", id,genre)
TypeError: function takes at most 2 arguments (3 given)"
I don't under stand why it says 3 given even though I gave two argument ( id, genre )
enter image description here
Problems with code
This line returns the cursor. In order to get the result, you will need to call terminal operations such as .fetchall(), .fetchmany() or .fetchone()
id = db.execute("INSERT INTO shows (title) VALUES(?)", (title,))
As you didn't call the terminal operator or print out the result, you wouldn't know that the INSERT operation returns None, not actual id
Minor: generally, it isn't advised to call variables the same name as built-in Python functions. See id.
As I suggested in the comment, you will need to insert a tuple:
db.execute(
"INSERT INTO genres (show_id, genre) VALUES (?, ?)",
(id_, genre)
)
Solution
You will need to select title from the shows table after insertion. Also, retrieve the id from the selection and then insert it into the genres table.
The simplified version of the code, to showcase how to do it:
import csv
import sqlite3
open("shows.db", "w").close()
con = sqlite3.connect('shows.db')
db = con.cursor()
db.execute("CREATE TABLE shows (id INTEGER, title TEXT, PRIMARY KEY(id))")
db.execute("CREATE TABLE genres (show_id INTEGER, genre TEXT, FOREIGN KEY(show_id) REFERENCES shows(id))")
shows = ["FRIENS", "Game of Trhones", "Want", "Scooby Doo"]
genres = ["Comedy", "Fantasy", "Action", "Cartoon"]
for ind, show in enumerate(shows):
db.execute("INSERT INTO shows (title) VALUES(?)", (show,))
id_ = con.execute(
"SELECT id FROM shows WHERE title = :show ORDER BY id DESC LIMIT 1",
{
"show": show
},
).fetchone()
db.execute(
"INSERT INTO genres (show_id, genre) VALUES (?, ?)",
(id_[0], genres[ind], )
)
con.commit()
con.close()
For more details, check my code on the GitHub.
SELECT statement may look a bit complex. What it does in a nutshell, it takes the matching title and returns the largest id. As titles may be the same, you always take the last inserted that matches.
General suggestions on debugging issues like that
Try using print as much as possible
Use dir and type functions to see methods and be able to google types
Search docs or examples on GitHub
I can see your issue. It's because you're trying the add in the id and genre into the query like they do in the sqlite3 documentation. In the documentation they did what your trying to do in a tuple but you did it in the function call.
Try this instead:
sql_query = ("INSERT INTO genres (show_id, genre) VALUES(?, ?)", id, genre)
db.execute(sql_query)
Or you could put it into a one-liner:
# notice how there is 2 parenthesis
# ↓ ↓
db.execute(("INSERT INTO genres (show_id, genre) VALUES(?, ?)", id, genre))
# ↑ ↑
I have 2 things I needed help with:
1) I am unsure as to how I can check if a table exists in python using the sqlite3 library.
2) I am unsure as to how I can save variables from the program to a database. I want to be able to check if UserDetails exists before making the database.
I've been reading around and everyone is doing stuff differently,
Here is the section of my code that is responsible for saving the variables:
connection = sqlite3.connect("UserDetails.db")
crsr = connection.cursor()
#create table
sql_command = table_creator
crsr.execute(sql_command)
#insert values into table
data_to_insert = (username, first_name, surname, age, user_salt, password_hash, date_today)
sql_command = """INSERT INTO UserDetails VALUES ((?, ?, ?, ?, ?, ?, ?), data_to_insert);"""
crsr.execute(sql_command)
connection.commit() #save changes
connection.close() #terminate connection
and in case you want to see table_creator it looks like this:
table_creator = '''CREATE TABLE `UserDetails` (
`Username` VARCHAR(8) NOT NULL,
`Firstname` VARCHAR(10) NOT NULL,
`Surname` VARCHAR(20) NOT NULL,
`Age` INT(2) NOT NULL,
`Salt` VARCHAR(10) NOT NULL,
`Hash` VARCHAR(64) NOT NULL,
`Date` DATE NOT NULL,
PRIMARY KEY (`UserName`)
);'''
I will appreciate and feedback or support.
I am still learning to code, and my CompSci teacher doesnt teach us Python specifically, so what I know is self taught.
Oh and this is the error message I get:
Traceback (most recent call)
File "c:/Users/Arslan/Project A2/login.py", line 99, in <module>
save_details()
File "c:/Users/Arslan/Project A2/login.py", line 93, in save_details
crsr.execute(sql_command)
sqlite3.OperationalError: no such column: data_to_insert
How to check if a table exists or no :
The first way :
Use this query:
SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';
Modify {table_name} with your table to check
There are two cases :
. If the cursor equal to 0 ==> the table does not exist
Else, the table exists
The second way:
Use :
PRAGMA table_info(table_name)
example:
The third way :
Use this query :
select 1 from table
It will return the constant 1 for every row of the table if the table exists, or nothing if not.
There are many other ways, but I listed the best in my opinion.
How to save variables from the program to a database:
To insert data into sqlite3, you can use :
cursor.execute("insert into UserDetails values (?, ?, ?, ?, ?, ?, ?)", (username, firstname, surname, age, salt, hash, date))
DON'T USE (SQL injection):
cursor.execute("insert into UserDetails values ('{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}')".format(username, firstname, surname, age, salt, hash, date))
Don't forget :
conn.commit()
Or you can use instead of it the connection as a context manager:
with conn:
# then cursor.execute..
1) I am unsure as to how I can check if a table exists in python using the sqlite3 library.
Use CREATE TABLE IF NOT EXISTS:
table_creator = '''CREATE TABLE IF NOT EXISTS `UserDetails` (
`Username` VARCHAR(8) NOT NULL,
`Firstname` VARCHAR(10) NOT NULL,
...
);'''
2) I am unsure as to how I can save variables from the program to a database.
You can pass variables for insert with the following syntax:
data_to_insert = (username, first_name, surname, age, user_salt, password_hash, date_today)
sql_command = '''INSERT INTO UserDetails VALUES (?, ?, ?, ?, ?, ?, ?)''';
crsr.execute(sql_command, data_to_insert )
I have to read data from Excel and insert it into Table...
For this I am using Python 2.7, pymssql and xlrd modules...
My sql connection is working fine and I am also able to read data from Excel properly.
My table structure :
CREATE TABLE MONTHLY_BUDGET
(
SEQUENCE INT IDENTITY,
TRANSACTION_DATE VARCHAR(100),
TRANSACTION_REMARKS VARCHAR(1000),
WITHDRAWL_AMOUNT VARCHAR(100),
DEPOSIT_AMOUNT VARCHAR(100),
BALANCE_AMOUNT VARCHAR(100)
)
My excel values are like this :
02/01/2015 To RD Ac no 147825000874 7,000.00 - 36,575.74
I am having problem while inserting multiple values in the table... I am not sure how to do this...
import xlrd
import pymssql
file_location = 'C:/Users/praveen/Downloads/OpTransactionHistory03-01-2015.xls'
#Connecting SQL Server
conn = pymssql.connect (host='host',user='user',password='pwd',database='Practice')
cur = conn.cursor()
# Open Workbook
workbook = xlrd.open_workbook(file_location)
# Open Worksheet
sheet = workbook.sheet_by_index(0)
for rows in range(13,sheet.nrows):
for cols in range(sheet.ncols):
cur.execute(
" INSERT INTO MONTHLY_BUDGET VALUES (%s, %s, %s, %s, %s)", <--- Not sure!!!
[(sheet.cell_value(rows,cols))])
conn.commit()
Error :
ValueError: 'params' arg () can be only a tuple or a dictionary.
The docs are here : http://pymssql.org/en/stable/pymssql_examples.html
The exception you are getting says that the "'params' arg() can be only a tuple or a dictionary" but you're passing in a list. Also, your parameter list appears to be a single tuple instead of a list with 4 values. Try changing
cur.execute(
" INSERT INTO MONTHLY_BUDGET VALUES (?, ?, ?, ?, ?)", <--- Not sure!!!
[(sheet.cell_value(rows,cols))])
to
cur.execute(
" INSERT INTO MONTHLY_BUDGET VALUES (?, ?, ?, ?, ?)", <--- Not sure!!!
(sheet.cell_value(rows,cols)))
... or maybe
cur.execute(
" INSERT INTO MONTHLY_BUDGET VALUES (?, ?, ?, ?, ?)", <--- Not sure!!!
((sheet.cell_value(rows,cols))))
NB: untested. I've always changed how the bind variables in your SQL are being called.
I have been trying with the below code:
import sqlite3
data_person_name = [('Michael', 'Fox'),
('Adam', 'Miller'),
('Andrew', 'Peck'),
('James', 'Shroyer'),
('Eric', 'Burger')]
con = sqlite3.connect(":memory:")
c = con.cursor()
c.execute('''CREATE TABLE q1_person_name
(name_id integer auto_increment primary key,
first_name varchar(20) NOT NULL,
last_name varchar(20) NOT NULL)''')
c.executemany('INSERT INTO q1_person_name VALUES (?,?,?)', data_person_name)
for row in c.execute('SELECT * FROM q1_person_name'):
print row
Can somebody help me in making the name_id automatically incremented ?
In SQLite, INTEGER PRIMARY KEY column is auto-incremented. There is also an AUTOINCREMENT keyword. When used in INTEGER PRIMARY KEY AUTOINCREMENT, a
slightly different algorithm for Id creation is used.
#!/usr/bin/python
import sqlite3
data_person_name = [('Michael', 'Fox'),
('Adam', 'Miller'),
('Andrew', 'Peck'),
('James', 'Shroyer'),
('Eric', 'Burger')]
con = sqlite3.connect(":memory:")
with con:
c = con.cursor()
c.execute('''CREATE TABLE q1_person_name
(name_id INTEGER PRIMARY KEY,
first_name varchar(20) NOT NULL,
last_name varchar(20) NOT NULL)''')
c.executemany('INSERT INTO q1_person_name(first_name, last_name) VALUES (?,?)', data_person_name)
for row in c.execute('SELECT * FROM q1_person_name'):
print(row)
This code now works OK.
c.executemany('INSERT INTO q1_person_name(first_name, last_name) VALUES (?,?)', data_person_name)
When using auto-increment, we have to explicitly state the column names, omitting the
one that is auto-incremented.
$ ./test.py
(1, u'Michael', u'Fox')
(2, u'Adam', u'Miller')
(3, u'Andrew', u'Peck')
(4, u'James', u'Shroyer')
(5, u'Eric', u'Burger')
This is the output of the code example.
It seems that you've done it already. So there's no need to reference that field when you insert.
INSERT INTO q1_person_name (first_name, last_name) VALUES (?,?)
Replace the first ? in executemany statement with null.
So the following line can be rewritten:
c.executemany('INSERT INTO q1_person_name VALUES (?,?,?)', data_person_name)
as
c.executemany('INSERT INTO q1_person_name VALUES (null,?,?)', data_person_name)
Try like this:
c.execute('''CREATE TABLE q1_person_name
(name_id integer primary key AUTOINCREMENT,
first_name varchar(20) NOT NULL,
last_name varchar(20) NOT NULL)''')