Python SQLlite3 loop to find row with fetchone - python

I have a snippet in my code that needs to find a mac address in the database, then print a statement to show what row it's been found in. I will then use that row number to update the timestamp column in that row.
My sqlite3 DB looks like this:
CREATE TABLE IF NOT EXISTS My_TABLENAME (mac_addr TEXT, timestamp TEXT, location TEXT, serialno TEXT)"
The code looks like this.
import sqlite3 as lite
con = lite.connect("database.db")
con.row_factory = lite.Row
cur = con.cursor()
cur.execute('''SELECT mac_addr, timestamp, (SELECT COUNT(*) FROM MY_TABLENAME AS t2 WHERE t2.mac_addr <= t1.mac_addr) AS i FROM My_TABLENAME AS t1 ORDER BY timestamp, mac_addr''')
_data = cur.fetchone()
if str(_data[0]) != '5c:f5:da:e0:dd:44':
cur.fetchone()
else:
print "Found the device in row", str(_data[2])
when I run the code in the python cli I get the below when I print the _data variable after doing the first fetchone()
>>> _data
(u'34:0a:ff:b2:75:78', u'1433940972.03946', 135)
>>>
So I can see that the row currently in the _data variable is row 135 (this changes obviously).
But when I run the code snippet I posted uptop I get the following output, which makes me think the loop is not working. Am I doing something wrong?
>>> import sqlite3 as lite
>>> con = lite.connect("database.db")
>>> con.row_factory = lite.Row
>>> cur = con.cursor()
>>> cur.execute('''SELECT mac_addr, timestamp, (SELECT COUNT(*) FROM My_TABLENAME AS t2 WHERE t2.mac_addr <= t1.mac_addr) AS i FROM My_TABLENAME AS t1 ORDER BY timestamp, mac_addr''')
<sqlite3.Cursor object at 0x7ff99fc0a8f0>
>>> _data = cur.fetchone()
>>> if str(_data[0]) != '5c:f5:da:e0:dd:44':
... cur.fetchone()
... else:
... print "Found the device in row", str(_data[2])
...
(u'18:83:31:61:83:8c', u'1433940974.39824', 74)
>>>
Any advice would be great please.

Thanks. I managed to change the IF statement to a For loop and got success that way.
Although I do think a WHERE statement would be more efficient in the long run. I'll experiment with it and see.
Thanks

cur.execute('''SELECT mac_addr, timestamp,
(SELECT COUNT(*) FROM My_TABLENAME AS t2
WHERE t2.mac_addr <= t1.mac_addr) AS i
FROM My_TABLENAME AS t1 WHERE mac_addr = ?
ORDER BY timestamp, mac_addr''', '5c:f5:da:e0:dd:44')
It's faster.

Related

Execute SQL for different where clause from Python

I am trying to print SQL result through python code, where I an trying to pass different predicates of the where clause from a for loop. But the code only taking the last value from the loop and giving the result.
In the below example I have two distinct id values 'aaa' and 'bbb'. There are 4 records for id value = 'aaa' and 2 records for the id value = 'bbb'.
But the below code only giving me the result for the id value ='bbb' not for id value 'aaa'
Can anyone help to identify what exactly wrong I am doing?
import pymysql
db = pymysql.connect(host="localhost", user="user1", passwd="pass1", db="db1")
cur = db.cursor()
in_lst=['aaa', 'bbb']
for i in in_lst:
Sql = "SELECT id, val, typ FROM test123 Where id='{inpt}'".format(inpt=i)
print(Sql)
cur.execute(Sql)
records = cur.fetchall()
print(records)
db.close()
The result I am getting as below
C:\Python34\python.exe C:/Users/Koushik/PycharmProjects/Test20161204/20170405.py
SELECT id, val, typ FROM test123 Where id='bbb'
(('bbb', 5, '1a'), ('bbb', 17, '1d'))
Process finished with exit code 0
import pymysql
db = pymysql.connect(host="localhost", user="root", passwd="1234", db="sakila")
cur = db.cursor()
in_lst=['1', '2']
for i in in_lst:
Sql = "SELECT * FROM actor Where actor_id='{inpt}'".format(inpt=i)
print(Sql)
cur.execute(Sql)
records = cur.fetchall()
print(records)
db.close()
Indentation is your problem, please update the code according to your needs...
Within your for loop, you're formatting the sql statement to replace "{inpt}" with "aaa". However, before you do anything with that value, you're immediately overwriting it with the "bbb" version.
You would need to either:
Store the results somehow before the next iteration of the loop, then process them outside of the loop.
Process the results within the loop.
Something like the following will give you a list containing both results from the fetchall() calls:
import pymysql
db = pymysql.connect(host="localhost", user="user1", passwd="pass1", db="db1")
cur = db.cursor()
in_lst=['aaa', 'bbb']
records = list()
for i in in_lst:
Sql = "SELECT id, val, typ FROM test123 Where id='{inpt}'".format(inpt=i)
print(Sql)
cur.execute(Sql)
records.append(cur.fetchall())
print(records)
db.close()

Trying to log date and time into sqlite3

My goal is to take two variables, xdate and xtime and store them into an sqlite database in two separate columns using a python scripts. My code is
from datetime import datetime
import sqlite3 as mydb
import sys
con = mydb.connect('testTime.db')
def logTime():
i=datetime.now()
xdate = i.strftime('%Y-%m-%d')
xtime = i.strftime('%H-%M-%S')
return xdate, xtime
z=logTime()
this is where I get hung up I tried
try:
with con:
cur = con.cursor
cur.execute('INSERT INTO DT(Date, Time) Values (?,?)' (z[0],z[1]))
data = cur.fetchone()
print (data)
con.commit()
except:
with con:
cur=con.cursor()
cur.execute("CREATE TABLE DT(Date, Time)')
cur.commit()
I keep getting none when I try to fetch the data.
Any tips or recommended readings??
You are executing a insert query, it's result is not having any thing to fetch. You should run a select query and then fetch the data.
fetchone()
Fetches the next row of a query result set, returning a single sequence, or None when no more data is available.
An example -
>>> cur.execute('INSERT INTO DT(Date, Time) Values (?,?)', (z[0],z[1]))
<sqlite3.Cursor object at 0x0353DF60>
>>> print cur.fetchone()
None
>>> cur.execute('SELECT Date, Time from DT')
<sqlite3.Cursor object at 0x0353DF60>
>>> print cur.fetchone()
(u'2016-02-25', u'12-46-16')

Python not able to modify MySQL but user can

Sorry if this question is stupid, I am 2 days into learning python
I have been beating my head against a wall trying to understand why my python script can run SELECT statements but not UPDATE or DELETE statements.
I believe this would be a MySQL issue and not a Python issue but I am no longer able to troubleshoot
pcheck.py
import re
import time
import json
import MySQLdb
import requests
from array import *
conn = MySQLdb.connect([redacted])
cur = conn.cursor()
sql1 = "SELECT pkey,pmeta FROM table1 WHERE proced = 0 LIMIT 1"
cur.execute(sql1)
row = cur.fetchone()
while row is not None:
print "row is: ",row[0]
rchk = [
r"(SHA256|MD5)",
r"(abc|def)"
]
for trigger in rchk:
regexp = re.compile(trigger)
pval = row[1]
if regexp.search(pval) is not None:
print "matched on: ",row[0]
sql2 = """INSERT INTO table2 (drule,dval,dmeta) VALUES('%s', '%s', '%s')"""
try:
args2 = (trigger, pval, row[1])
cur.execute(sql2, args2)
print(cur._last_executed)
except UnicodeError:
print "pass-uni"
break
else:
pass
sql3 = """UPDATE table1 SET proced=1 WHERE pkey=%s"""
args3 = row[0]
cur.execute(sql3, args3)
print(cur._last_executed)
row = cur.fetchone()
sql3 = """DELETE FROM table1 WHERE proced=1 AND last_update < (NOW() - INTERVAL 6 MINUTE)"""
cur.execute(sql3)
print(cur._last_executed)
cur.close()
conn.close()
print "Finished"
And the actual (and suprisingly expected) output:
OUTPUT
scrape#:~/python$ python pcheck.py
row is: 0GqQ0d6B
UPDATE table1 SET proced=1 WHERE pkey='0GqQ0d6B'
DELETE FROM table1 WHERE proced=1 AND last_update < (NOW() - INTERVAL 6 MINUTE)
Finished
However, the database is not being UPDATED. I checked that the query was making it to MySQL:
MySQL Log
"2015-12-14 22:53:56","localhost []","110","0","Query","SELECT `pkey`,`pmeta` FROM `table1` WHERE `proced`=0 LIMIT 200"
"2015-12-14 22:53:57","localhost []","110","0","Query","UPDATE `table1` SET `proced`=1 WHERE `pkey`='0GqQ0d6B'"
"2015-12-14 22:53:57","localhost []","110","0","Query","DELETE FROM table1 WHERE proced=1 AND last_update < (NOW() - INTERVAL 6 MINUTE)"
However proced value for row 0GqQ0d6B is still NOT 1
If I make the same queries via Sqlyog (logged in as user) the queries work as expected.
These kind of issues can be very frustrating. You sure there's no extra spaces here?
print "row is:*"+row[0]+"*"
Perhaps comment out the
for trigger in rchk:
section, and sprinkle some print statements around?
As the commenter Bob Dylan was able to deduce the cursor needed to be committed after the change.

is there a way to do a insert an request the scope_identity() using pyodbc to sql server 2005

I have this great pyodbc lib. I try the code below, it supposed to insert a row and return the row id but it didn't work. by the way I'm using sql server 2005 on server and client is windows os
...
con = pyodbc.connect('conectionString', autocommit = True)
cur = con.execute(
"insert into sometable values('something');
select scope_identity() as id"
)
for id in cur:
print id
...
some idea?
Try this, one statement with the OUTPUT clause
cur = con.execute(
"insert into sometable OUTPUT INSERTED.idcolumn values('something')"
)
row = cur.fetchone()
lastrowid = row[0]
Edit: This should get around the issue commented by Joe S.
Using SCOPE_IDENTITY() is the way to go as there are limitations and quirks using OUTPUT and ##IDENTITY because of triggers.
Using your code snipped, you just need to add a call to nextset to get the id.
...
con = pyodbc.connect('conectionString', autocommit = True)
cur = con.execute(
"insert into sometable values('something');
select scope_identity() as id"
)
cur.nextset()
for id in cur:
print id
...

How to check with python if a table is empty?

Using python and MySQLdb, how can I check if there are any records in a mysql table (innodb)?
Just select a single row. If you get nothing back, it's empty! (Example from the MySQLdb site)
import MySQLdb
db = MySQLdb.connect(passwd="moonpie", db="thangs")
results = db.query("""SELECT * from mytable limit 1""")
if not results:
print "This table is empty!"
Something like
import MySQLdb
db = MySQLdb.connect("host", "user", "password", "dbname")
cursor = db.cursor()
sql = """SELECT count(*) as tot FROM simpletable"""
cursor.execute(sql)
data = cursor.fetchone()
db.close()
print data
will print the number or records in the simpletable table.
You can then test if to see if it is bigger than zero.

Categories