How to add an action to a mysql, python written database - python

So I'm trying to make a project for school where a database stores the check_in and check_out time form an RFID card using a RFID reader.
create table attendance_check(
id INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
date_id DATE NOT NULL DEFAULT CURRENT_DATE,
user_id INT UNSIGNED NOT NULL,
name VARCHAR(255) NOT NULL,
clock_id TIME NOT NULL DEFAULT CURRENT_TIME,
Action VARCHAR(255) NOT NULL,
PRIMARY KEY ( id )
);
The database looks like this and for "Action" I want to add "in" and "out". I manage to add the "in" but can't figure out how to make a look-up and add an "out".
This is the code so far. I've tried 10 different variations already, I also have a database that stores the Users.
while True:
lcd.clear()
lcd.message('Place Card to\nrecord attendance')
id, text = reader.read()
cursor.execute("Select id, name FROM users WHERE rfid_uid="+str(id))
result = cursor.fetchone()
lcd.clear()
name = result[1]
number = result [0]
action1 = "in"
action2 = "out"
if cursor.rowcount >= 1:
lcd.message("Welcome " + name)
add = ("INSERT INTO attendance_check (user_id, name, Action) VALUES (%s, %s, %s)")
date = (numar, nume, action1)
cursor.execute(add, date)
db.commit()
else:
lcd.message("User does not exist.")
time.sleep(2)
I've tried to use if statements inside that checks if an action is there and if it's "in" it should add "out" but it never worked
It looks like this so far

Related

Cannot to insert record into table Incorrect number of bindings supplied

Cannot to insert into ShopifyMonitor table record (there 2 field: id, name)
full traceback of error:
File "D:\Related To Python (Tutorials)\Python-Test\Working With Database\goo.py", line 174, in <module>
c.execute(make_shopify_name, (shopify_name))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 10 supplied.
.
get_site = str(input('Enter site here: '))
url = fix_url(get_site)
shopify_name = fix_url(get_site, True)
basepath = os.path.dirname(__file__)
db_name = '{}/shopify.sqlite3'.format(basepath)
sql_create_projects_table = """ CREATE TABLE IF NOT EXISTS ShopifyMonitor (
id integer PRIMARY KEY AUTOINCREMENT,
name text UNIQUE NOT NULL
);"""
sql_create_tasks_table = """ CREATE TABLE IF NOT EXISTS Product (
id integer PRIMARY KEY AUTOINCREMENT,
product_id text NOT NULL,
updated_at text NOT NULL,
title text NOT NULL,
link_to_product text UNIQUE NOT NULL,
vendor text NOT NULL,
sku text NOT NULL,
quantity text NOT NULL,
options text,
price text NOT NULL,
collection_id text,
collection_updated text,
shopify_name text NOT NULL,
FOREIGN KEY(shopify_name) REFERENCES ShopifyMonitor(name)
);"""
make_shopify_name = '''INSERT INTO ShopifyMonitor(name) VALUES (?) '''
conn = create_connection(db_name)
if conn is not None:
# create projects table
create_table(conn, sql_create_projects_table)
# create tasks table
create_table(conn, sql_create_tasks_table)
else:
print("Error! cannot create the database connection.")
c = conn.cursor()
c.execute(make_shopify_name, (shopify_name))
conn.commit()
It looks like your post is mostly code; please add some more details.add some more details.
The issue is subtle:
c.execute(make_shopify_name, (shopify_name))
Should be:
c.execute(make_shopify_name, (shopify_name,)) # note comma after shopify_name
The second parameter passed into execute should be a tuple of parameters for the query - even if there's only one parameter, it still has to be a tuple.
At the moment all you have is parentheses around a variable name - the parentheses will basically be ignored by Python as they don't mean anything.
It's a common misconception that it's the parentheses that make a tuple - it's not, it's the comma:
x = (1) # x is 1
x = 1, # x is a tuple containing a single value, the integer 1
x = (1,) # as above - but the parentheses aren't actually required syntactically here

Inserting date string into SQLite from Python giving unexpected results

As the title states, I'm trying to insert a date (formatted as a string) into a SQLite database. This works, however the date is not showing up correctly in SQLite.
Here is a subset of my code:
print("Connecting to the database...")
sqlite_file = './sqlite_db/cfr_changes.db'
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
today_date = datetime.now().strftime("%Y-%m-%d")
print(today_date)
print("Inserting tracker into database...")
c.execute("INSERT INTO DATE (`date_id`) VALUES(" + today_date + ")")
c.executemany("INSERT INTO TRACKER (`cfr_status`, `comment`, `mdu`, `iwb`, `obsolete`, `date_id`) VALUES(?,?,?,?,?, " + today_date + ")", list(tracker_df.to_records(index=False)))
#print(c.fetchall())
conn.commit()
conn.close()
Printing 'today_date' returns what I'd expect:
2018-10-24
However when I check the records in SQLite through the terminal, the date is shown as:
1984
Note that 'date_id' is a VARCHAR(255), and date formatting should not be an issue. I would think that is simply a string being stored into a string (or close enough).
Can anyone inform me why this doesn't work as expected?
For reference, here is how the 'TRACKER' and 'DATE' tables were created:
CREATE TABLE `DATE` (
`date_id` VARCHAR(255) NOT NULL PRIMARY KEY);
CREATE TABLE `TRACKER` (
`tracker_id` INTEGER NOT NULL PRIMARY KEY,
`cfr_status` VARCHAR(255) NOT NULL,
`mdu` BOOLEAN, `iwb` BOOLEAN,
`obsolete` BOOLEAN, `comment` VARCHAR(255), `date_id` VARCHAR(255) NOT NULL, FOREIGN KEY (`date_id`) REFERENCES DATE(`date_id`));
Any help is appreciated.
The issue is that you are just concatenating variables into your insert statements without worrying about whether the format they are in makes any sense. For example, to insert a date literal into SQLite you should be using this:
'2018-10-24'
Here is an example of how you may use prepared statements to do a proper insert:
today_date = datetime.now().strftime("%Y-%m-%d")
c.execute("INSERT INTO DATE (date_id) VALUES (?)", ("'" + today_date + "'",))

How to get columns from a query in python?

I have that query in a python program:
And i should create a multidimensional array (if it possible) or four arrays from this query for every column from the query.
Can you suggest an elegant way to solve it?
conn = #connection to the server
cursor=conn.cursor()
query = (" select id, name, phone, city from guest")
cursor.execute(query)
results = cursor.fetchall
for i in results:
print i
cursor.close()
conn.close()
Not elegant but it may assist to unravel the mysterious Python Connector Cursor Class and transfers the list of tuples (see Copperfield comment) with the data from the query, into a list (phoneList) of dictionaries (entries) with details of each entry in the database, that might be easier to work with in your python script:
# ref: https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor.html
import mysql.connector
db = 'test'
table = 'phonebook'
phoneList = []
drop_table = ("DROP TABLE IF EXISTS {};").format(table)
# By default, the starting value for AUTO_INCREMENT is 1, and it will increment by 1 for each new record.
# To let the AUTO_INCREMENT sequence start with another value, use the following SQL statement:
# ALTER TABLE phonebook AUTO_INCREMENT=100;
create_table = ("CREATE TABLE {} ("
"id int NOT NULL AUTO_INCREMENT,"
"name varchar(30) NOT NULL,"
"phone varchar(30) NOT NULL,"
"city varchar(30) NOT NULL,"
"PRIMARY KEY (id))"
" ENGINE=InnoDB DEFAULT CHARSET=latin1;").format(table)
Names = {'Bill':{'phone':'55123123','city':'Melbourne'},
'Mary':{'phone':'77111123','city':'Sydney'},
'Sue':{'phone':'55888123','city':'Melbourne'},
'Harry':{'phone':'77777123','city':'Sydney'},
'Fred':{'phone':'88123444','city':'Yongala'},
'Peter':{'phone':'55999123','city':'Melbourne'}}
cnx = mysql.connector.connect(user='mysqluser', password='xxxx',host='127.0.0.1',database=db)
cursor = cnx.cursor(dictionary=True) # key to using **row format
cursor.execute(drop_table)
cursor.execute(create_table)
# populate db
for name,detail in dict.items(Names):
sql = ("INSERT INTO {} (name,phone,city) VALUES ('{}','{}','{}')".format(table,name,detail['phone'],detail['city']))
cursor.execute(sql)
sql = ("SELECT id,name,phone,city FROM {}".format(table))
cursor.execute(sql)
for row in cursor:
print("{id} {name} {phone} {city}".format(**row))
phoneList.append(row)
print phoneList[0]['name'],phoneList[0]['city']
print phoneList[3]['name'],phoneList[3]['phone']
for entries in phoneList: # list of dictionaries
print entries['name'],entries
for entries in phoneList:
for k,v in dict.items(entries):
print k,v
print "\n"
cnx.close()

Working with databases with Python: Course registration data in JSON

I am able to get my Python code to run print the desired results, but my problem is with the SQLite table. I was asked to apply this SQL command to the tables:
SELECT hex(User.name || Course.title || Member.role ) AS X
FROM User JOIN Member JOIN Course
ON User.id = Member.user_id AND Member.course_id = Course.id
ORDER BY X
I was able to execute the command in SQLite, but according to the instructions for this project, X is supposed to start with 416 in row one of the results column produced. However, the X I got for row 1 in the results was:
43616C6962736933313030
Here is what I wrote in Python so far:
import sqlite3
import json
#Working with Java and Sqlite
conn = sqlite3.connect('rosterdb.sqlite')
cur = conn.cursor()
cur.executescript('''
DROP TABLE IF EXISTS User;
DROP TABLE IF EXISTS Member;
DROP TABLE IF EXISTS Course;
CREATE TABLE User(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT UNIQUE
);
CREATE TABLE Member(
user_id INTEGER UNIQUE,
course_id INTEGER UNIQUE,
role INTEGER,
PRIMARY KEY (user_id, course_id)
);
CREATE TABLE Course(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
title TEXT UNIQUE
);
''')
#primary key for junction table is composite of both user_id and course_id
fname = raw_input("Enter file name:")
if (len(fname) < 1): fname = 'roster_data.json'
#prompts for file name
str_data = open(fname).read()
json_data = json.loads(str_data)
#opens the file and reads it all
#loads the json data and now is a python list
for entry in json_data:
title = entry[1];
name = entry [0];
role = entry[2];
#["Charley, "sill0", 1] represents the name, course title, and role
print name, title, role
cur.execute('''INSERT or IGNORE INTO User (name)
VALUES (?)''', (name, ))
cur.execute('SELECT id FROM User WHERE name = ?',(name, ))
user_id = cur.fetchone()[0]
cur.execute('''INSERT or IGNORE INTO Course (title)
VALUES (?)''', (title, ))
cur.execute('SELECT id FROM Course WHERE title = ?', (title, ))
course_id = cur.fetchone()[0]
cur.execute('''INSERT or REPLACE INTO Member (user_id, course_id, role)
VALUES (?,?,?)''', (user_id, course_id, role))
#INSERT, SELECT AND FETCHONE STATEMENTS
conn.commit()
Here is the JSON data that I was working with. It is about course registration for students: roster_data.json Here is the link to it:
https://pr4e.dr-chuck.com/tsugi/mod/sql-intro/roster_data.php?PHPSESSID=9addd537cfe55c03585d2bfaa757f6b0
I am not sure if I implemented the "role" key correctly. Thank you for your inputs!
The problem is that you made Member.course_id unique. Thus you can have no more members than courses. Using REPLACE in INSERT or REPLACE into Member hides this error.
Just drop UNIQUE constraint on Member.course and you will get expected result.

How to import csv data with parent/child (category-subcategory) hierarchy to MySQL using Python

I am importing a csv file containing a parent/child (category-subcategory) hierarchy to MySQL, using Python's MySQLdb module. Here is an example csv file:
vendor,category,subcategory,product_name,product_model,product_price
First vendor,category1,subcategory1,product1,model1,100
First vendor,category1,subcategory2,product2,model2,110
First vendor,category2,subcategory3,product3,model3,130
First vendor,category2,subcategory4,product5,model7,190
In MySQL I want to use a category table with a hierarchical structure, like this:
CREATE TABLE IF NOT EXISTS `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`status` tinyint(1) NOT NULL,
PRIMARY KEY (`category_id`),
KEY `parent_id` (`parent_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
My question is: How do I determine the parent_id in this table?
Here is the Python script I have so far:
import MySQLdb
import csv
con = MySQLdb.connect('localhost', 'root', '', 'testdb', use_unicode=True, charset='utf8')
with con:
cur = con.cursor()
csv_data = csv.reader(file('test.csv'))
csv_data.next()
for row in csv_data:
cur.execute("SELECT manufacturer_id FROM manufacturer WHERE name=%s", [row[0]],)
res = cur.fetchall()
if res:
vendor_id = res[0][0]
else:
cur.execute("INSERT INTO manufacturer (name) VALUES (%s)", (row[0],))
vendor_id = cur.lastrowid
cur.execute("SELECT category_id FROM category_description WHERE name=%s", [row[2]])
res = cur.fetchall()
if res:
category_id = res[0][0]
else:
# What parent_id should be inserted here?
cur.execute("INSERT INTO category (`status`, `parent_id`) VALUES (%s,%s)", (1,))
category_id = cur.lastrowid
cur.execute("INSERT INTO category_description (category_id, name) VALUES (%s,%s)", (category_id,row[2],))
cur.execute("INSERT INTO product (model, manufacturer_id, price,) VALUES (%s, %s, %s)", (row[4], `vendor_id`, row[8],))
product_id = cur.lastrowid
cur.execute("INSERT INTO product_to_category (product_id, category_id) VALUES (%s, %s)", (product_id, category_id,))
cur.commit()
Here are the definitions of the other tables used in my example:
CREATE TABLE IF NOT EXISTS `manufacturer` (
`manufacturer_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
PRIMARY KEY (`manufacturer_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
CREATE TABLE IF NOT EXISTS `category_description` (
`category_id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`category_id`,`language_id`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
CREATE TABLE IF NOT EXISTS `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`model` varchar(64) NOT NULL,
`manufacturer_id` int(11) NOT NULL,
`price` decimal(15,4) NOT NULL DEFAULT '0.0000',
PRIMARY KEY (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
CREATE TABLE IF NOT EXISTS `product_to_category` (
`product_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`product_id`,`category_id`),
KEY `category_id` (`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
In a hierarchical table structure, any member at the top of its hierarchy has no parents. I would probably show this with a NULL parent ID but based on the way you've defined your category table, it looks like you want to show this by giving the value 0 for the parent ID.
Since you have fixed-depth hierarchies with only two levels (category and subcategory), the task is relatively simple. For each row of the CSV data, you need to:
Check whether the parent (row[1]) is in the table; if not, insert it with a parent ID of 0.
Get the category_id of the parent from step 1.
Check whether the child (row[2]) is in the table; if not, insert it with a parent ID equal to the category_id from step 2.
In your example code, you never access the parent (row[1]); you need to insert this into the table for it to have an ID that the child can refer to. If you've already inserted the parents before this point, you should probably still check to make sure it's there.
You have some other problems here:
The PK of your category_description table is defined on a column that you forgot to define in the table (language_id).
You should really be using InnoDB in this physical model so that you can enforce foreign key constraints in category_description, product and product_to_category.
In your example, cur.commit() is going to throw an exception – that's a method of the Connection object in MySQLdb. Of course, COMMIT isn't implemented for MyISAM tables anyway, so you could also avoid the exception by removing the line entirely.
Referencing row[8] is also going to throw an exception, according to the CSV data you've shown us. (This is a good example of why you should test your MCVE to make sure it works!)
If you do switch to InnoDB – and you probably should – you can use with con as cur: to get a cursor that commits itself when you exit the with block. This saves a couple lines of code and lets you manage transactions without micromanaging the connection object.

Categories