So I have the following error:
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'I, Alexander_Bernard16#milton.edu, D0NBT6)' at line 1")
Here's my code:
cnx = MySQLdb.connect(
user=username, passwd=password, host=hostname, db=databaseName)
cursor = cnx.cursor()
cursor.execute("CREATE TABLE if not exists gotchaTable(id int(11) PRIMARY KEY "
"AUTO_INCREMENT, selfFirstName TEXT NOT NULL, selfLastName TEXT NOT NULL, "
"selfGrade TEXT NOT NULL, selfCode TEXT NOT NULL, targetCode TEXT NOT "
"NULL);")
cnx.commit()
add_data = (
"INSERT INTO gotchaTable (selfFirstName, selfLastName, selfGrade, selfCode, targetCode) VALUES ({0}, {1}, {2}, {3}, {4});"
)
studentlist = []
with open('Gotcha.csv', 'rb') as csvfile:
gotchaData = csv.DictReader(csvfile)
for row in gotchaData:
student = Student(
row['First'], row['Last'], row['Class'], row['Email'])
studentlist.append(student)
studentlist = randomList(studentlist)
for x in xrange(1, len(studentlist)):
studentlist[x].target = studentlist[
x + 1] if x < len(studentlist) - 1 else studentlist[0]
cursor.execute(add_data.format(studentlist[x].first, studentlist[x].last,
studentlist[x].grade, studentlist[x].email,
studentlist[x].code, studentlist[x].target.code))
cnx.commit()
print studentlist[x].getData()
And here's my student class:
class Student(object):
"""docstring for Student"""
def __init__(self, f, l, c, e):
self.first = f
self.last = l
self.grade = c
self.email = e
self.code = id_generator()
self.target = None
def getData(self):
return self.first + ' ' + self.last + ' ' + self.grade + ' ' + self.email + ' ' + self.code
Im trying to make a program that gets data from a csv (which already works) and puts it into a SQL table. How do i fix the error 1064, i've tried using "%s" instead of '{0}' but i get the same error. Any suggestions?
the id_generator() method returns a string of random characters.
randomList(a) makes the array random.
Don't use string formatting to parameterize an SQL query - this is dangerous and, as you can see, error-prompt. Instead, let the MySQL driver worry about it:
add_data = """
INSERT INTO
gotchaTable
(selfFirstName, selfLastName, selfGrade, selfCode, targetCode)
VALUES
(%s, %s, %s, %s, %s)
"""
Then, when you call execute() pass parameters in a separate argument:
cursor.execute(add_data, [
studentlist[x].first,
studentlist[x].last,
studentlist[x].grade,
# studentlist[x].email, ALSO WATCH THIS ONE (there are only 5 placeholders in the query)
studentlist[x].code,
studentlist[x].target.code
])
Related
I am trying to create a database using python. When the program runs no error occurs, however nothing happens. Is there a line I am missing?
class create_db:
def __init__(self):
self.conn = sqlite3.connect("EXAMPLE.db")
self.c = self.conn.cursor()
def create_tables(self, Tables):
for table_name, field in Tables.items():
self.c.execute('CREATE TABLE IF NOT EXISTS ' + table_name + '(' + field + ')')
self.conn.commit()
def main():
db = create_db()
tables = {"CUSTOMERS": '''CustomerID integer,
Customer_Name text,
primary key (CustomerID)'''}
db.create_tables(tables)
main()
I have a function what is adding new records in to Mysql database after scanning a barcode. Function is working but there is a problem with returning result on the App screen.
When I scan the barcode first time it does not return any results even when i can see that the new record was created. But when i scan the barcode second time it returns only 1 record.
Edit:(added more about the issue)
And after that it is always -1 record, which would not be problem i could add +1 to all results but the problem is the first one, as it returns nothing at all.
I tried to use time.sleep(.3) between the queries but that did not have any effect.
I now wonder if the Python code is wrong or my SQL query should be somehow different.
def db_execute3(config, sql, val):
mydb = mysql.connector.connect(**config)
mycursor = mydb.cursor()
try:
mycursor.execute(sql, val)
mydb.commit()
except mysql.connector.Error as err:
if err.errno == errorcode.CR_CONN_HOST_ERROR:
popip.open()
Clock.schedule_once(popip.dismiss, 3)
elif err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
popx.open()
Clock.schedule_once(popx.dismiss, 3)
elif err.errno == errorcode.ER_BAD_DB_ERROR:
popdb.open()
Clock.schedule_once(popdb.dismiss, 3)
elif err.errno == errorcode.ER_NO_REFERENCED_ROW_2:
popbr.open()
Clock.schedule_once(popbr.dismiss, 3)
else:
mycursor.close()
def inbsort_btndwn(self, _):
cont = self.container_no.text.upper()
barc = self.sku_barcode.text.upper()
sort_worknumb = self.sort_worknumb.text.upper()
val = (sort_worknumb, cont, barc)
valx = (cont,barc)
if barc is "" and cont is "":
errorsound.play()
self.pallet_sku.text = ""
self.number_sku.text = ""
Clock.schedule_once(self.focus_container_no, 0.2)
elif barc is "" and cont is not "":
errorsound.play()
self.pallet_sku.text = ""
self.number_sku.text = ""
Clock.schedule_once(self.focus_sku_barcode, 0.2)
else:
try:
mydb = mysql.connector.connect(**config)
checkupd = mydb.cursor(prepared=True)
sqlq = "select * from inb_container where `container_no` = %s and `sku_code` = %s;"
checkupd.execute(sqlq, valx)
record = checkupd.fetchone()
if record is None:
errorsound.play()
popuni.content.text = "No records for scanned Barcode!"
popuni.open()
Clock.schedule_once(popuni.dismiss, 2)
Clock.schedule_once(self.clear_barcode, .2)
Clock.schedule_once(self.focus_sku_barcode, 0.21)
else:
correctsound.play()
sql = "INSERT INTO inb_sor_con (`work_number`, `container_no`,`sku_barcode`) VALUES (%s, %s, %s)"
db_execute3(config, sql, val)
sqlz = "SELECT ic.sort_box,ic.sort_pallet FROM inb_container ic, " \
"inb_sor_con ib WHERE ic.container_no =ib.container_no and ic.sku_code = ib.sku_barcode " \
"and ic.container_no = %s and ic.sku_code = %s"
valz = (cont, barc)
checkupd.execute(sqlz, valz) #v289-ukan1012044-n10 #msku8416005
myresult = checkupd.fetchall()
for row in myresult:
xxx = "Scanned: {} of: {}".format(checkupd.rowcount, row[0])
zzz = "{}".format(row[1])
self.pallet_sku.text = zzz
self.number_sku.text = xxx
Clock.schedule_once(self.clear_barcode, 0.2)
Clock.schedule_once(self.focus_sku_barcode, 0.21)
except mysql.connector.Error as err:
print(err.errno)
pass
This is the database:
create table inb_container(
`container_no` varchar(25) NOT NULL,
`sku_code` varchar(40) NOT NULL,
`sort_box` int(5),
`sort_pcs` int(6),
`sort_pallet` varchar(3),
Unique (container_no,sku_code)
);
create table inb_sor_con(
`id_scan` int(6) auto_increment not null primary key,
`work_number` varchar(12),
`container_no` varchar(25) NOT NULL,
`sku_barcode` varchar(40) NOT NULL,
`sort_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (work_number) REFERENCES user_logins(work_number),
FOREIGN KEY (container_no) REFERENCES inb_container(container_no));
As mentioned, I'd suggest refactoring your code so it's not mixing UI code with database access. That way you can more easily test each bit of your program (either manually, from a separate module) or automatically using unit tests or such.
You can also freely create new cursors, don't reuse a single one.
Here's one such refactoring...
def find_container(db, *, container_no, barcode):
cursor = db.cursor()
cursor.execute(
"select * from inb_container where `container_no` = %s and `sku_code` = %s",
(container_no, barcode),
)
return cursor.fetchone()
def insert_sor_con(db, *, sort_worknumb, container_no, barcode):
cursor = db.cursor()
cursor.execute(
"INSERT INTO inb_sor_con (`work_number`, `container_no`,`sku_barcode`) VALUES (%s, %s, %s)",
(sort_worknumb, container_no, barcode),
)
db.commit()
def get_scan_results(db, *, container_no, barcode):
cursor = db.cursor()
cursor.execute(
"""
SELECT ic.sort_box,ic.sort_pallet
FROM inb_container ic, inb_sor_con ib
WHERE (
ic.container_no = ib.container_no AND
ic.sku_code = ib.sku_barcode AND
ic.container_no = %s AND
ic.sku_code = %s
)""",
(container_no, barcode),
)
return cursor.fetchall()
def show_error(message):
errorsound.play()
popuni.content.text = message
popuni.open()
Clock.schedule_once(popuni.dismiss, 2)
class SomeUI:
def inbsort_btndwn(self, _):
container_no = self.container_no.text.upper()
barcode = self.sku_barcode.text.upper()
sort_worknumb = self.sort_worknumb.text.upper()
if not (barcode and container_no):
errorsound.play()
self.pallet_sku.text = ""
self.number_sku.text = ""
if not barcode:
Clock.schedule_once(self.focus_sku_barcode, 0.2)
else:
Clock.schedule_once(self.focus_container_no, 0.2)
return
try:
with mysql.connector.connect(**config) as mydb:
container_record = find_container(
mydb, container_no=container_no, barcode=barcode
)
if container_record:
correctsound.play()
insert_sor_con(
mydb,
sort_worknumb=sort_worknumb,
container_no=container_no,
barcode=barcode,
)
scan_results = list(
get_scan_results(mydb, container_no=container_no, barcode=barcode)
)
for sort_box, sort_pallet in scan_results:
self.pallet_sku.text = "{}".format(sort_pallet)
self.number_sku.text = "Scanned: {} of: {}".format(
len(scan_results), sort_box
)
else:
show_error("No records for scanned Barcode!")
except Exception as exc:
# may want to use `traceback.print_traceback()` here for more detail
print(exc)
show_error(f"Error: {exc}")
Clock.schedule_once(self.clear_barcode, 0.2)
Clock.schedule_once(self.focus_sku_barcode, 0.21)
i want to some of the column of sqlite darabase through one gui window and the rest through another however am getting error
c.execute('INSERT INTO information VALUES(:name,:branch,:reg)',
sqlite3.OperationalError: table information has 6 columns but 3 values were supplied
This is how I create table dynamically on the fly and populate it:
def create_table(ptbl):
""" Assemble DDL (Data Definition Language) Table Create statement and build
sqlite3 db table
Args:
string: new db table name.
Returns:
Status string, '' or 'SUCCESS'.
"""
retval = ''
sqlCmd = ''
try:
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
if ptbl == 'TBL_EXAMPLE':
sqlCmd = 'CREATE TABLE IF NOT EXISTS ' + ptbl + ' (FIELD1 TEXT, FIELD2 INTEGER, FIELD3 TEXT, ' \
'FIELD4 TEXT, FIELD5 TEXT)'
else:
pass
if sqlCmd != '':
c.execute(sqlCmd)
conn.commit()
conn.close()
retval = 'SUCCESS'
except Error as e:
retval = 'FAIL'
print(e)
return retval
and the populate the table having 5 fields like this:
def populate_tbl_file_marker_linenums(p_fml_tbl, p_fml_datafile):
""" Read csv and load data into TBL_FILE_MARKER_LINENUMS table ...
Args:
p_fml_tbl (TEXT) target table name
p_fml_datafile (TEXT) name of csv file to load into table
Returns:
retval (TEXT) - Status of method, e.g., 'SUCCESS'
"""
retval = ''
mode = 'r'
try:
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
csv_dataset = open(p_fml_datafile, mode)
csv_reader = csv.reader(csv_dataset)
c.executemany('INSERT INTO ' + p_fml_tbl + ' (FIELD1, FIELD2, FIELD3, FIELD4, FIELD5) VALUES (?, ?, ?, ?, ?)', csv_reader)
conn.commit()
conn.close()
retval = 'SUCCESS'
except Error as e:
print(e)
return retval
I used the following code to get items from sqlite3 database
def get(self, item_name, attrs=True): #get attr from item and return as dict, if attr==True: get all items
conn = self.conn
if attrs: #all
return conn.execute('SELECT * FROM %s WHERE __item_key__ = "%s";' %(self.table, item_name))
else:
command = 'SELECT '
for attr in attrs:
command+= attr+' '
command+='FROM %s WHERE __item_key__ = "%s";' %(self.table, item_name)
return conn.execute(command)
print(get('name1'))
the code print the following:
<sqlite3.Cursor at 0x213d4c0f490>
instead of the values from the table.
When I try this:
get('name1')[0]
it returns:
TypeError: 'sqlite3.Cursor' object is not subscriptable
Full code:
import sqlite3 as sql
import sqlite3 as sql
class db:
'''
This class turns dicts into sqlite databases
and output sqlite databases as dicts
'''
def __init__(self, db_name, table_name): #open or create a database
conn = sql.connect(db_name).cursor()
self.table = table_name
self.conn = conn
def create(self, table_name, cols):
command = "CREATE TABLE %s(_item_key_ TEXT," % table_name
for key, value in cols.items():
command+="%s %s," %(key, value)
command=command[:-1]
command+=");"
self.conn.execute(command)
self.table = table_name
def get(self, item_name, attrs=True): #get attr from item and return as dict, if attr==True: get all items
conn = self.conn
if attrs: #all
return conn.execute('SELECT * FROM %s WHERE _item_key_ = "%s";' %(self.table, item_name))
else:
command = 'SELECT '
for attr in attrs:
if type(attr) == str:
attr = '"'+attr+'"'
command+= str(attr)+' '
command+='FROM %s WHERE _item_key_ = "%s";' %(self.table, item_name)
return conn.execute(command).fetchall()
def change(self, item_name, attrs): #change certain attrs of item
command = 'UPDATE %s SET ' %self.table
for key, value in attrs:
command += '%s=%s,'%(key, value)
command = command[:-1]+' WHERE _item_name_ = "'+item_name+'";'
def add(self, item_name, attrs): #add an item with attrs to database
command = 'INSERT INTO %s VALUES ("%s",' %(self.table, item_name)
for attr in attrs:
if type(attr) == str:
attr = '"'+attr+'"'
command += str(attr)+','
command = command[:-1]+');'
#print(command)
self.conn.execute(command)
def close(self): #close database
self.conn.close()
The table is supposed to look like the following (although I never saw it):
__item_name__ A B
---------------------------
'name1' 123 'hi'
'name2' 344 'bye'
Does anyone know how this works?
edit: I realized some bugs in create() and add(). However, after fixing some stuff it still prints the same thing in get().
It returns that no cursor object found.
If you want to get the results you need to add these lines:
cur = conn.cursor() # create a cursor to your connection
cur.execute(your_query) # execute your query
results = cur.fetchall() # fetch the results
Also don't forget to iterate over the cursor after results = cur.fetchall():
for row in results:
A = row[0]
B = row[1]
Should revise all code and implement this self.conn.commit() after self.conn.execute(---).
self.conn.execute(command)
self.conn.commit() #<--- THIS NEW line, to after .execute()
self.table = table_name
I am trying to dynamically generate MySQL insert/update queries given a csv file.
I have a csv file hobbies.csv:
id,name,hobby
"1","rick","coding"
"2","mike","programming"
"3","tim","debugging"
I then have 2 functions: 1 to generate the queries, 1 to update the database:
generate_sql.py
from connect_to_database import read_db_config
from config_parser import read_csv_files
from update_db import insert_records
import csv
def generate_mysql_queries():
csv_file_list, table_list, temp_val, temp_key, temp_table, reader, header, data, data_list = ([] for i in range(9))
val_param = '%s'
query = ''
total_queries = 0
db = read_db_config(filename='config.ini', section='mysql')
csv_file_dict = read_csv_files(filename='config.ini', section='data')
for key, value in csv_file_dict.items():
temp_val = [value]
temp_key = [key]
csv_file_list.append(temp_val)
table_list.append(temp_key)
for index, files in enumerate(csv_file_list):
with open("".join(files), 'r') as f:
reader = csv.reader(f)
header.append(next(reader))
data.append([row for row in reader])
for d in range(len(data[index])):
val_param_subs = ','.join((val_param,) * len(data[index][d]))
total_queries += 1
query = """INSERT INTO """ + str(db['database']) + """.""" + """""".join('{0}'.format(t) for t in table_list[index]) + \
"""(""" + """, """.join('{0}'.format(h) for h in header[index]) + """) VALUES (%s)""" % val_param_subs + \
""" ON DUPLICATE KEY UPDATE """ + """=%s, """.join(header[index]) + """=%s"""
data_list.append(data[index][d])
insert_records(query, data_list)
I then pass the query and data to insert_records() in update_db.py:
from mysql.connector import MySQLConnection, Error
from connect_to_database import read_db_config
def insert_records(query, data):
query_string = query
data_tuple = tuple(data)
try:
db_config = read_db_config(filename='config.ini', section='mysql')
conn = MySQLConnection(**db_config)
cursor = conn.cursor()
cursor.executemany(query, data_tuple)
print("\tExecuted!")
conn.commit()
except Error as e:
print('\n\tError:', e)
print("\n\tNot Executed!")
finally:
cursor.close()
conn.close()
The data passed into cursor.executemany(query, data_string) looks like the following (query is a string and data_tuple is a tuple):
query: INSERT INTO test.hobbies(id, name, hobby) VALUES (%s,%s,%s) ON DUPLICATE KEY UPDATE id=%s, name=%s, hobby=%s
data_tuple: (['1', 'rick', 'coding'], ['2', 'mike', 'programming'], ['3', 'tim', 'debugging'])
Given these two parameters, I get the following error:
Error: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '%s, name=%s, hobby=%s' at line 1
I've tried passing in the same string non-dynamically by just sending the full string without the '%s' parameters and it works fine. What am I missing? Any help is much appreciated.
Probably is the use of the triple double quotes in python. When you use this
query = """INSERT INTO """ + str(db['database']) + """.""" + """""".join('{0}'.format(t) for t in table_list[index]) + \
"""(""" + """, """.join('{0}'.format(h) for h in header[index]) + """) VALUES (%s)""" % val_param_subs + \
""" ON DUPLICATE KEY UPDATE """ + """=%s, """.join(header[index]) + """=%s"""
You're saying to python that everything is a string including %s.