sqlite3 python negative row count [duplicate] - python

I'm trying to insert new records into SQLite database from Python code.
con = sqlite.connect(connectionString)
cur = con.cursor()
countOfNewItems = 0
for ...
try:
con.execute("insert or ignore into items ...")
countOfNewItems += cur.rowcount
except:
cur.close()
con.close()
print "Error when inserting item '%s' to database." % item
exit(1)
cur.close()
con.commit()
con.close()
print "%d new items have been inserted." % countOfNewItems
My code reports negative number of inserted records (-5141).
Because my database was empty, I could find out how many records were inserted via command line
select count(*) from items;
4866
Could you advise me what's wrong. Why the two values don't match and why it's negative?

http://docs.python.org/library/sqlite3.html#sqlite3.Cursor.rowcount
Although the Cursor class of the sqlite3 module implements this attribute, the database engine’s own support for the determination of “rows affected”/”rows selected” is quirky.
and
As required by the Python DB API Spec, the rowcount attribute “is -1 in case no executeXX() has been performed on the cursor or the rowcount of the last operation is not determinable by the interface”.

Try cur.execute instead of con.execute. cur.rowcount then returns 1 for me for a simple insert.

Related

pyodbc not updating table

I query a table then loop through it to Update another table.
The console Prints shows correct data.
Not sure how to debug the cursor.execute for the UPDATE query.
It is not updating on the table. It's not a permission issue. If I run update command on my SQL workbench it works fine.
cursor = conn.cursor()
cursor.execute("Select Account_Name FROM dsf_CS_WebAppView")
for row in cursor.fetchall():
try:
cursor.execute("Select fullpath FROM customerdesignmap WHERE
fullpath LIKE '%{}%'".format(row.Account_Name))
rows = cursor.fetchall()
print(len(cursor.fetchall()))
if len(rows) > 0:
for rowb in rows:
print(rowb.fullpath)
print(row.Account_Name)
if len(row.Account_Name) > 2:
cursor.execute("UPDATE customerdesignmap SET householdname = {}, msid = {} WHERE fullpath LIKE '{}'".format(row.Account_Name, row.UniqueProjectNumber, rowb.fullpath))
conn.commit()
except:
pass
Consider a pure SQL solution as SQL Server supports UPDATE and JOIN across multiple tables. This avoids the nested loops, cursor calls, and string formatting of SQL commands.
UPDATE m
SET m.householdname = v.Account_Name,
m.msid = v.UniqueProjectNumber
FROM customerdesignmap m
JOIN dsf_CS_WebAppView v
ON m.fullpath LIKE CONCAT('%', v.Account_Name, '%')
In Python, run above in a single cursor.execute() with commit() call.
cursor.execute('''my SQL Query''')
conn.commit()

Issue with inserting parameter values into MySQLdb.execute()

My code executes a query and then for each row in the result set tries to execute another query using values from that row.
import MySQLdb as mdb
try:
con = mdb.connect('localhost', 'root', '', 'cccorder_uk');
with con:
cur = con.cursor()
cur.execute("SELECT code, name, box_size, commodity_code, country_of_origin FROM cccorder_uk.stocks")
rows = cur.fetchall()
for row in rows:
# split the code and take colour and size
code = row[0].split('-')
product_code = code[0]
sql = """SELECT stock_groups.name FROM stock_groups_styles_map, stock_groups WHERE stock_groups_styles_map.style='%s'""" % (product_code,)
cur.execute(sql)
results = cur.fetchall()
print results
except mdb.Error, e:
print "Error %d: %s" % (e.args[0],e.args[1])
sys.exit(1)
finally:
if con:
con.close()
When I print results I get an empty tuple, but if I hard code the product_code, for example sql = """SELECT stock_groups.name FROM stock_groups_styles_map, stock_groups WHERE stock_groups_styles_map.style='EP22'""", this returns the results I expect.
Why is my code printing an empty tuple?
Python's string-format operator % isn't smart enough to quote args for MySQL -- pass args to the database execute function, which will pass the args to MySQL correctly.
Example:
cur.execute("SELECT stock_groups.name FROM stock_groups_styles_map, stock_groups WHERE stock_groups_styles_map.style=%s", product_code)
See: How can I format strings to query with mysqldb in Python?

How to test if a table already exists?

I'm working on a scrabblecheat program
Following some examples I have the following code below which uses SQLite for a simple database to store my words.
However it tells me I can't recreate the database table.
How do I write in a check for if there is already a table named spwords, then skip trying to create it?
The error:
(<class 'sqlite3.OperationalError'>, OperationalError('table spwords already exists',), None)
The Code:
def load_db(data_list):
# create database/connection string/table
conn = sqlite.connect("sowpods.db")
#cursor = conn.cursor()
# create a table
tb_create = """CREATE TABLE spwords
(sp_word text, word_len int, word_alpha text, word_score int)
"""
conn.execute(tb_create) # <- error happens here
conn.commit()
# Fill the table
conn.executemany("insert into spwords(sp_word, word_len, word_alpha, word_score) values (?,?,?,?)", data_list)
conn.commit()
# Print the table contents
for row in conn.execute("select sp_word, word_len, word_alpha, word_score from spwords"):
print (row)
if conn:
conn.close()
The query you're looking for is:
SELECT name FROM sqlite_master WHERE type='table' AND name='spwords'
So, the code should read as follows:
tb_exists = "SELECT name FROM sqlite_master WHERE type='table' AND name='spwords'"
if not conn.execute(tb_exists).fetchone():
conn.execute(tb_create)
A convenient alternative for SQLite 3.3+ is to use a more intelligent query for creating tables instead:
CREATE TABLE IF NOT EXISTS spwords (sp_word text, word_len int, word_alpha text, word_score int)
From the documentation:
It is usually an error to attempt to create a new table in a database that already contains a table, index or view of the same name. However, if the "IF NOT EXISTS" clause is specified as part of the CREATE TABLE statement and a table or view of the same name already exists, the CREATE TABLE command simply has no effect (and no error message is returned). An error is still returned if the table cannot be created because of an existing index, even if the "IF NOT EXISTS" clause is specified.
conn = sqlite3.connect('sowpods.db')
curs = conn.cursor()
try:
curs.execute('''CREATE TABLE spwords(sp_word TEXT, word_len INT, word_alpha TEXT,word_score INT)''')
conn.commit()
except OperationalError:
None
https://docs.python.org/2/tutorial/errors.html
I believe if it already exists you can just skip the error and move directly into the inserting of the data
I am not a fan of the bounce the CREATE off the database approach. You should know whether the table exists so that first time initialization can occur.
Here is the same query based answer but based on general purpose functions:
def getTables(conn):
"""
Get a list of all tables
"""
cursor = conn.cursor()
cmd = "SELECT name FROM sqlite_master WHERE type='table'"
cursor.execute(cmd)
names = [row[0] for row in cursor.fetchall()]
return names
def isTable(conn, nameTbl):
"""
Determine if a table exists
"""
return (nameTbl in getTables(conn))
Now the top code is
if not(isTable(conn, 'spwords')):
# create table and other 1st time initialization
Here is an example that shows how to cleanly consume the result from fetchone() call:
table_exists(conn:sqlite3.Connection, tbl_name:string) -> bool:
(count,) = conn.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='{}'".format(tbl_name)).fetchone()
return (count > 0)

Python: tuple indices must be integers, not str when selecting from mysql table

I have following method that I select all the ids from table and append them to a list and return that list. But when execute this code I end up getting tuple indicies must be integers... error. I have attached the error and the print out along with my method:
def questionIds(con):
print 'getting all the question ids'
cur = con.cursor()
qIds = []
getQuestionId = "SELECT question_id from questions_new"
try:
cur.execute(getQuestionId)
for row in cur.fetchall():
print 'printing row'
print row
qIds.append(str(row['question_id']))
except Exception, e:
traceback.print_exc()
return qIds
Printing what my method does:
Database version : 5.5.10
getting all the question ids
printing row
(u'20090225230048AAnhStI',)
Traceback (most recent call last):
File "YahooAnswerScraper.py", line 76, in questionIds
qIds.append(str(row['question_id'][0]))
TypeError: tuple indices must be integers, not str
The python standard mysql library returns tuples from cursor.execute. To get at the question_id field you'd use row[0], not row['question_id']. The fields come out in the same order that they appear in the select statement.
A decent way to extract multiple fields is something like
for row in cursor.execute("select question_id, foo, bar from questions"):
question_id, foo, bar = row
There are multiple cursor types in the MySQLdb module. The default cursor returns the data in a tuple of tuples. When we use a dictionary cursor, the data is sent in a form of Python dictionaries. This way we can refer to the data by their column names. Source
#!/usr/bin/python
# -*- coding: utf-8 -*-
import MySQLdb as mdb
con = mdb.connect('localhost', 'testuser', 'test623', 'testdb')
with con:
cur = con.cursor(mdb.cursors.DictCursor)
cur.execute("SELECT * FROM Writers LIMIT 4")
rows = cur.fetchall()
for row in rows:
print row["Id"], row["Name"]
I know the question is old, but I found another way to do it that I think it is better than the accepted solution. So I'll just leave it here in case anyone needs it.
When creating the cursor you can use
cur = connection.cursor(dictionary=True);
which will allow you to do exactly what you want without any additional modifications.
rows = cur.fetchall()
for row in rows:
print "%s %s %s" % (row["Id"], row["Name"], row["Price"])
you can see here: enter link description here ,I think its your want
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlite3 as lite
con = lite.connect('test.db')
with con:
con.row_factory = lite.Row # its key
cur = con.cursor()
cur.execute("SELECT * FROM Cars")
rows = cur.fetchall()
for row in rows:
print "%s %s %s" % (row["Id"], row["Name"], row["Price"])
To retrieve data from database use dictionary cursor
import psycopg2
import psycopg2.extras
con = psycopg2.connect(database="test", user="test", password="test", host="localhost", port="5432")
if con != None:
print "Connection Established..!\n"
else:
print "Database Connection Failed..!\n"
cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute("SELECT * FROM emp")
rows = cur.fetchall()
for row in rows:
print "%s %s %s" % (row["id"],row["name"],row["address"])
print "\nRecords Display Successfully"
con.commit()
con.close()
Integer indices are not allowed. To get it working you can declare the DICT as specified below:
VarName = {}
Hope this works for you.
row is a tuple. When you do row['question_id'], you are trying to access a tuple using a string index which gives you an error.

TypeError: 'NoneType' object is not iterable

I need to process mysql data one row at a time and i have selected all rows put them in a tuple but i get the error above.
what does this mean and how do I go about it?
Provide some code.
You probably call some function that should update database, but the function does not return any data (like cursor.execute()). And code:
data = cursor.execute()
Makes data a None object (of NoneType). But without code it's hard to point you to the exact cause of your error.
It means that the object you are trying to iterate is actually None; maybe the query produced no results?
Could you please post a code sample?
The function you used to select all rows returned None. This "probably" (because you did not provide code, I am only assuming) means that the SQL query did not return any values.
Try using the cursor.rowcount variable after you call cursor.execute(). (this code will not work because I don't know what module you are using).
db = mysqlmodule.connect("a connection string")
curs = dbo.cursor()
curs.execute("select top 10 * from tablename where fieldA > 100")
for i in range(curs.rowcount):
row = curs.fetchone()
print row
Alternatively, you can do this (if you know you want ever result returned):
db = mysqlmodule.connect("a connection string")
curs = dbo.cursor()
curs.execute("select top 10 * from tablename where fieldA > 100")
results = curs.fetchall()
if results:
for r in results:
print r
This error means that you are attempting to loop over a None object. This is like trying to loop over a Null array in C/C++. As Abgan, orsogufo, Dan mentioned, this is probably because the query did not return anything. I suggest that you check your query/databse connection.
A simple code fragment to reproduce this error is:
x = None
for each i in x:
#Do Something
pass
This may occur when I try to let 'usrsor.fetchone' execute twice. Like this:
import sqlite3
db_filename = 'test.db'
with sqlite3.connect(db_filename) as conn:
cursor = conn.cursor()
cursor.execute("""
insert into test_table (id, username, password)
values ('user_id', 'myname', 'passwd')
""")
cursor.execute("""
select username, password from test_table where id = 'user_id'
""")
if cursor.fetchone() is not None:
username, password = cursor.fetchone()
print username, password
I don't know much about the reason. But I modified it with try and except, like this:
import sqlite3
db_filename = 'test.db'
with sqlite3.connect(db_filename) as conn:
cursor = conn.cursor()
cursor.execute("""
insert into test_table (id, username, password)
values ('user_id', 'myname', 'passwd')
""")
cursor.execute("""
select username, password from test_table where id = 'user_id'
""")
try:
username, password = cursor.fetchone()
print username, password
except:
pass
I guess the cursor.fetchone() can't execute twice, because the cursor will be None when execute it first time.
I know it's an old question but I thought I'd add one more possibility. I was getting this error when calling a stored procedure, and adding SET NOCOUNT ON at the top of the stored procedure solved it. The issue is that earlier selects that are not the final select for the procedure make it look like you've got empty row sets.
Try to append you query result to a list, and than you can access it. Something like this:
try:
cursor = con.cursor()
getDataQuery = 'SELECT * FROM everything'
cursor.execute(getDataQuery)
result = cursor.fetchall()
except Exception as e:
print "There was an error while getting the values: %s" % e
raise
resultList = []
for r in result:
resultList.append(r)
Now you have a list that is iterable.

Categories

Resources