How do I iterate over a SQLite database using the Python API? - python

Basically I want to be able to choose an amount of numbers using for x...in range(y amount of numbers) and inject them into an SQLite database. However I receive the following error:
line 17, in <module>
values (?)""") (number)
sqlite3.ProgrammingError: Incorrect number of bindings supplied.
The current statement uses 1, and there are 0 supplied.
Here is my non functioning code. All input is appreciated.:
import sqlite3
conn = sqlite3.connect("usernames.sqlite")
c = conn.cursor()
c.execute('''create table numbers (number)''')
for number in range(21):
# Insert a row of data
c.execute("""insert into numbers
values (?)"""),(number)
# Save (commit) the changes
conn.commit()
# We can also close the cursor if we are done with it
c.close()

execute takes a tuple of values in the case of "?" parameters, so you need to write:
c.execute("""insert into numbers values (?)""", (number,))
(number,) is a way to define a tuple with one element.
And by the way, you can do this more efficiently using the executemany method:
c.executemany(
"""insert into numbers values (?)""",
[(number,) for number in range(21)]
)

You've got a misplaced closed paren in values (?)"""),(number).
Not sure why this wasn't a syntax error, though. Is this the exact code that you were using?

Related

Comparing SQL results with Python

I was looking for a way to my program to take 2 values from my database, compare them and update or insert some value.
I tried in sqlite3 but I didn't find a good solution and I tried on python, but when I run the program, the values are different and never match. I already look on google, here on stack overflow, but didn't find anything.
cursor.execute("select * from [Sistema]")
Teste = cursor.fetchall()
cursor.execute("select [SistemaOperacional] from [Sistema] where [SistemaOperacional] = 'teste'")
comparacao = cursor.fetchall()
testando = comparacao
for row in Teste:
#I was checking the values to see if they where equal
print(comparação[0]) #Value ('teste',)
print(row[0]) #Value 'teste'
if row[0] == comparação[0]:
cursor.execute("Update [Sistema] set [SistemaOperacional] = '1' where [VersaoBanco] = 3")
print('Executado')
break
else:
cursor.execute("insert into [Sistema] values ('9','9','1')")
print('não')
break
the output whas
('teste',)
teste
não
I wasn't finding a solution for this in sql, that's why I tried with python, but I'm open to listen any other suggestion than python
It's a pretty common problem for people unfamiliar with Python/MySQL to run into troubles receiving tuples back from querying. comparacao[0] is a tuple. Tuples are compared lexicographically by element, so you'd have to retrieve the first element (like #Gwyn Evans said) e.g. comparação[0][0] in order to compare it to your string row.
Here is a link to Python docs about comparisons: https://docs.python.org/2.0/ref/comparisons.html
I could be on the wrong track here, but isn't your comparação[0] itself a tuple, so you probably want to be comparing comparação[0][0] with row[0].

Forcing the for loop to start with the same ligne

I want to force the for loop to start always with the same ligne, so that the order of all lignes of the dataset still always the same.
In other words, when I'm searching the index of the ligne with id=15, I found always a diffrent result.
Here is my code:
`import psycopg2 as p
conn = p.connect("dbname=Chicago user=postgres password=admin host=localhost ")
cur = conn.cursor()
cur.execute("select * from chicago_2po_4pgr")
nbrows = cur.rowcount
rows = cur.fetchall()
for r in range(0,nbrows):
id=rows[r][0]
if id==15:
print(r,rows[r][0],rows[r][1])`
The result of the first run is:
`56153 15 4271616`
(r is 56153)
The result of the second run (of the same code) is:
`126523 15 4271616`
(r is 126523)
Any suggestion of how can I edit my code to have always the same order of lignes?
Add an ORDER BY clause. SQL queries without order by can return results in any arbitrary order.
If the data being queried can be changed (insert, update or delete) then the record at position 15 can change. You could query a specific key value, or grab the result set and index it by a key, to get a consistent result.

python sqlite3 selecting variables

I'm trying to select 3 variables in a sqlite3 statement. And putting this into 3 python variables, can't get it to work..
knifekingdb.execute("SELECT rank, rounds, date FROM knifekingdb WHERE steamid = ?", steamid)
I can put it into one list by assigning that statement to a python variabel. But i don't know how to split a list of integers and strings into different variabels.
Can you please help me, because i'm a bit stuck.
knifekingdb.execute(
"""SELECT rank, rounds, date
FROM knifekingdb WHERE steamid = ? LIMIT 1""", steamid)
try:
rank, rounds, date = knifekingdb.fetchone()
except TypeError:
# fetchone returned None because no row was found
# handle error here
raise

How to check if record exists with Python MySQdb

Im creating a python program that connects to mysql.
i need to check if a table contains the number 1 to show that it has connected successfully, this is my code thus far:
xcnx.execute('CREATE TABLE settings(status INT(1) NOT NULL)')
xcnx.execute('INSERT INTO settings(status) VALUES(1)')
cnx.commit()
sqlq = "SELECT * FROM settings WHERE status = '1'"
xcnx.execute(sqlq)
results = xcnx.fetchall()
if results =='1':
print 'yep its connected'
else:
print 'nope not connected'
what have i missed? i am an sql noob, thanks guys.
I believe the most efficient "does it exist" query is just to do a count:
sqlq = "SELECT COUNT(1) FROM settings WHERE status = '1'"
xcnx.execute(sqlq)
if xcnx.fetchone()[0]:
# exists
Instead of asking the database to perform any count operations on fields or rows, you are just asking it to return a 1 or 0 if the result produces any matches. This is much more efficient that returning actual records and counting the amount client side because it saves serialization and deserialization on both sides, and the data transfer.
In [22]: c.execute("select count(1) from settings where status = 1")
Out[22]: 1L # rows
In [23]: c.fetchone()[0]
Out[23]: 1L # count found a match
In [24]: c.execute("select count(1) from settings where status = 2")
Out[24]: 1L # rows
In [25]: c.fetchone()[0]
Out[25]: 0L # count did not find a match
count(*) is going to be the same as count(1). In your case because you are creating a new table, it is going to show 1 result. If you have 10,000 matches it would be 10000. But all you care about in your test is whether it is NOT 0, so you can perform a bool truth test.
Update
Actually, it is even faster to just use the rowcount, and not even fetch results:
In [15]: if c.execute("select (1) from settings where status = 1 limit 1"):
print True
True
In [16]: if c.execute("select (1) from settings where status = 10 limit 1"):
print True
In [17]:
This is also how django's ORM does a queryObject.exists().
If all you want to do is check if you have successfully established a connection then why are you trying to create a table, insert a row, and then retrieve data from it?
You could simply do the following...
sqlq = "SELECT * FROM settings WHERE status = '1'"
xcnx.execute(sqlq)
results = xcnx.fetchone()
if results =='1':
print 'yep its connected'
else:
print 'nope not connected'
In fact if your program has not thrown an exception so far indicates that you have established the connection successfully. (Do check the code above, I'm not sure if fetchone will return a tuple, string, or int in this case).
By the way, if for some reason you do need to create the table, I would suggest dropping it before you exit so that your program runs successfully the second time.
When you run results = xcnx.fetchall(), the return value is a sequence of tuples that contain the row values. Therefore when you check if results == '1', you are trying to compare a sequence to a constant, which will return False. In your case, a single row of value 0 will be returned, so you could try this:
results = xcnx.fetchall()
# Get the value of the returned row, which will be 0 with a non-match
if results[0][0]:
print 'yep its connected'
else:
print 'nope not connected'
You could alternatively use a DictCursor (when creating the cursor, use .cursor(MySQLdb.cursors.DictCursor) which would make things a bit easier to interpret codewise, but the result is the same:
if results[0]['COUNT(*)]':
# Continues...
Also, not a big deal in this case, but you are comparing an integer value to a string. MySQL will do the type conversion, but you could use SELECT COUNT(*) FROM settings WHERE status = 1 and save a (very small) bit of processing.
I recently improved my efficiency by instead of querying select, just adding a primary index to the unique column and then adding it. MySQL will only add it if it doesn't exist.
So instead of 2 statements:
Query MySQL for exists:
Query MySQL insert data
Just do 1 and it will only work if it's unique:
Query MySQL insert data
1 Query is better than 2.

In Python what could cause a for loop to randomly go backwards in value?

What can cause an iterator to go forwards in a loop, and then backwards?
This is the code I'm using to loop through the table's primary key field. The primary key is being used to populate initial values in a separate table.
For loop:
for row in sampleDB.select_fromTable():
print row[0]
sampleDB.insert_toTable(row[0], 2.0)
sqllite insert statement:
def insert_toTable(self, primaryKey, initial):
c = self.conn.cursor()
c.execute('insert into insert_toTable VALUES(?, ?)', (primaryKey, initial))
if c.rowcount == 1:
print "Updated row.\n"
else:
print "Row does not exist.\n"
self.conn.commit()
c.close()
The select statement that creates the tuple to loop through:
def select_fromTable(self):
c = self.conn.cursor()
c.execute('select * from sampleTable')
c.close
return c
Here is an example table:
Primary Key Text
0 John
1 Sue
2 Bill
3 Tyler
Running the loop without the insert statement prints each unique key once, but if I add the call to the insert function (insert_toTable) I get this phenomenon:
0
Updated row.
1
Updated row.
0
Traceback (most recent call last):
sqlite3.IntegrityError: column urlid is not unique
The next iteration of the loop should be to the unique value "2" not back to "0"....
I can provide more sections of code if needed.
I suspect the results of this code may change depending on exactly which versions of sqlite and python are used.
Notice that your call to c.close in the select_fromTable method should be c.close(). This is a fortunate error, since you cannot iterate over the results of the query after the cursor is closed. However, the result is that you have two open cursors in the loop.
Try changing your select_fromTable method to:
def select_fromTable(self):
c = self.conn.cursor()
c.execute('select * from sampleTable')
results = c.fetchall()
c.close()
return results
and see what happens. I believe it will fix your problem.

Categories