Python Multiple Select Queries SQL - python

I am trying to run two select queries one from a puzzle table and one from a table that stores the ids of the puzzles a user has played. I want the ids from the puzzles selected and then the ids for the puzzles played selected so that i can compare the two lists to find the puzzles the users has not yet played.
I am having an issue because the first query runs correctly but the second isn't as it seems to be taking the two values from the first query. How do i stop this? Its like i need to close the connection before running the next select query.
cur=connection.cursor()
cur.execute("SELECT id FROM puzzles WHERE approved =? AND level=? ",(1, UserLevel))
puzzle_rows=cur.fetchall()
print(puzzle_rows)
cur=connection.cursor()
cur.execute("SELECT id FROM puzzle_users WHERE name =?",(username))
played_rows=cur.fetchall()
print(played_rows)
not_played = [[x for x in puzzle_rows if x not in played_rows]]
print(not_played)
The error i get is:
conn.execute("SELECT id FROM puzzle_users WHERE name =?",(username))
sqlite3.ProgrammingError: Incorrect number of bindings supplied
The current statement uses 1, and there are 3 supplied.

There is an error in this line:
cur.execute("SELECT id FROM puzzle_users WHERE name =?",(username))
When you use 1-item tuple you should add a comma before the closing bracket:
cur.execute("SELECT id FROM puzzle_users WHERE name = ?", (username,))
Otherwise (username) is just a string, not tuple.

Related

Sqlite3 Python: can't use "limit" as column name

There are 6 columns and for some reason when my program gets to this bit of code during install, it simply creates a blank file with no table.
Through trial and error, I found the only thing that did not create a blank file was removing the limit row.
I have other code that runs and looks the same just for different databases and it works fine.
try:
# Connect to Database
conn = sqlite3.connect('databases/Categories.db')
cur = conn.cursor()
# Create Table
cur.execute("""CREATE TABLE categories (
priority text,
name text,
type text,
increment text,
total real,
limit real)""")
# Commit and Close
conn.commit()
conn.close()
except sqlite3.OperationalError:
pass
"limit" is an SQL keyword, for example, as in
SELECT foo
FROM bar
LIMIT 10;
If you want to use "limit" as a column name in sqlite, it needs to be quoted, in one of these ways:
'limit'
"limit"
[limit]
`limit`
So for example, your statement could be
cur.execute("""CREATE TABLE categories (
priority text,
name text,
type text,
increment text,
total real,
"limit" real)""")
Note that it must be quoted in other statements too, for example
"""INSERT INTO categories ("limit") VALUES (?);"""
I did some more testing and I fixed it by renaming the limit row to something else. Turns out, sqlite3 doesn't like rows named limit.

How can I delete rows from a database table where the ID isn't found in a tuple/list

Say I have a tuple of IDs:
ids = (1,2,3,4,5)
Using python, I want to delete every row from a database table (called schedule) that doesn't contain one of these IDs.
This is what I've tried:
delete_stmt = "DELETE from schedule WHERE ID NOT IN %s"
...
cursor.execute(delete_stmt, ids)
I've excluded the unnecessary code like connecting to the database, but I am connected properly.
I get an error message saying:
You have an error in your SQL syntax...
How can I fix my code to delete rows from the schedule table that aren't found in the ids tuple?
IN is a MySql Function, try it with ()
delete_stmt = "DELETE from schedule WHERE ID NOT IN (%s)"

Search through SQL table and delete row if cell already exists

I have a table using SQL Lite with Python. The size of the table always has 3 columns and could have many rows. Each of the cells are strings. Here is example table:
serial_num date_measured status
1234A 1-1-2015 passed
4321B 6-21-2015 failed
1423C 12-25-2015 passed
......
My program prompts me for a serial number. This is saved as a variable called serialNum. How can I delete (or overwrite) an entire row if serialNum equals any of the strings in the serial_num column in my table?
I've seen many examples on how to delete (or overwrite) a row in a table if I know all the values in each cell of that row, but my trouble is that the only cell that could ever be the same in each row would be the serial number. I need to so a search through the serial_number column and if any string in that column equals the current value of my serialNum variable, I need to delete (or overwrite) that row.
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
c.execute('''CREATE TABLE test (serial_num text, date_measured text, status text)''')
c.execute("INSERT INTO test VALUES ('1234A', '1-1-2015', 'passed')")
c.execute("INSERT INTO test VALUES ('4321B', '6-21-2015', 'failed')")
c.execute("INSERT INTO test VALUES ('1423C', '12-25-2015', 'passed')")
conn.commit()
Does anyone know a simple way to do this? I've seen others say that an ID must be used or a temporary table, but I would hope there might be an easier way to accomplish my task. Any advice would be great.
SQL suports this: simply use delete
"delete from test where serial_num=<some input>;"
or in this case
c.execute("delete from test where serial_num=%s;", serialNum);
There's no need to search through the list when using SQL. SQL is declarative: you tell it what to do using your query, not how to do it. Don't loop though all your rows to check which to delete: tell it what to delete and the database engine will find the best/fastest way to satisfy that goal.
Hope I well interpreted your question
for row in c.execute('SELECT * FROM test WHERE serial_num = ?', serialNum'):
# do whatever you want on row
print row
I was able to figure out a working solution:
sql = "DELETE FROM test WHERE serial_num = ?"
c.execute(sql, (serialNum,))
The comma after serialNum for some reason has to be there. Thank you #Michiel Arienfor the head start

Python SQlite ORDER BY command doesn't work

i just started out with programmming and wrote a few lines of code in pyscripter using sqlite3.
The table "gather" is created beforehand. i then select certain rows from "gather" to put them into another table. i try to sort this table by a specific column 'date'. But it doesn't seem to work. it doesn't give me an error message or something like that. It's just not sorted. If i try the same command (SELECT * FROM matches ORDER BY date) in sqlitemanager, it works fine on the exact same table! what is the problem here? i googled quite some time, but i don't find a solution. it's proobably something stupid i'm missing..
as i said i'm a total newbie. i guess you all break out in tears looking at the code. so if you have any tips how i can shorten the code or make it faster or whatever, you're very welcome :) (but everything works fine except the above mentioned part.)
import sqlite3
connection = sqlite3.connect("gather.sqlite")
cursor1 = connection.cursor()
cursor1.execute('Drop table IF EXISTS matches')
cursor1.execute('CREATE TABLE matches(date TEXT, team1 TEXT, team2 TEXT)')
cursor1.execute('INSERT INTO matches (date, team1, team2) SELECT * FROM gather WHERE team1=? or team2=?, (a,a,))
cursor1.execute("SELECT * FROM matches ORDER BY date")
connection.commit()
OK, I think I understand your problem. First of all: I'm not sure if that commit call is necessary at all. However, if it is, you'll definitely want that to be before your select statement. 'connection.commit()' is essentially saying, commit the changes I just made to the database.
Your second issue is that you are executing the select query but never actually doing anything with the results of the query.
try this:
import sqlite3
connection = sqlite3.connect("gather.sqlite")
cursor1 = connection.cursor()
cursor1.execute('Drop table IF EXISTS matches')
cursor1.execute('CREATE TABLE matches(date TEXT, team1 TEXT, team2 TEXT)')
cursor1.execute('INSERT INTO matches (date, team1, team2) SELECT * FROM gather WHERE team1=? or team2=?, (a,a,))
connection.commit()
# directly iterate over the results of the query:
for row in cursor1.execute("SELECT * FROM matches ORDER BY date"):
print row
you are executing the query, but never actually retrieving the results. There are two ways to do this with sqlite3: One way is the way I showed you above, where you can just use the execute statement directly as an iteratable object.
The other way is as follows:
import sqlite3
connection = sqlite3.connect("gather.sqlite")
cursor1 = connection.cursor()
cursor1.execute('Drop table IF EXISTS matches')
cursor1.execute('CREATE TABLE matches(date TEXT, team1 TEXT, team2 TEXT)')
cursor1.execute('INSERT INTO matches (date, team1, team2) SELECT * FROM gather WHERE team1=? or team2=?, (a,a,))
connection.commit()
cursor1.execute("SELECT * FROM matches ORDER BY date")
# fetch all means fetch all rows from the last query. here you put the rows
# into their own result object instead of directly iterating over them.
db_result = cursor1.fetchall()
for row in db_result:
print row
Try moving the commit before the SELECT * (I'm not sure 100% that this is an issue) You then just need to fetch the results of the query :-) Add a line like res = cursor1.fetchall() after you've executed the SELECT. If you want to display them like in sqlitemanager, add
for hit in res:
print '|'.join(hit)
at the bottom.
Edit: To address your issue of storing the sort order to the table:
I think what you're looking for is something like a clustered index. (Which doesn't actually sort the values in th table, but comes close; see here).
SQLIte doesn't have such such indexes, but you can simulate them by actually ordering the table. You can only do this once, as you're inserting the data. You would need an SQL command like the following:
INSERT INTO matches (date, team1, team2)
SELECT * FROM gather
WHERE team1=? or team2=?
ORDER BY date;
instead of the one you currently use.
See point 4 here, which is where I got the idea.

Check Python SQL Query result for variable

I'm new to Python and working with SQL queries. I have a database that contains a table with meetings and their date along with an ID. What I want to do is check what meetings are happening on today's date. The code below results in showing all the meeting ID's that are happening on todays date. However I then want to check if a certain meeting ID is in the results, which I have stored as a variable, and if it is in there to carry out an IF function so I can then elaborate.
cur.execute("SELECT id FROM meeting WHERE DATE(starttime) = DATE(NOW())")
for row in cur.fetchall() :
print row[0]
You can ask the database to tell you if the id is there:
cur.execute("SELECT id FROM meeting WHERE DATE(starttime) = DATE(NOW()) AND id=%s", (id,))
if cur.rowcount:
# The id is there
else:
# The id is not there.
I am assuming that you are using MySQLdb here; different database adapters use slightly different query parameter styles. Others might use ? instead of %s.

Categories