Get row count in MySQLdb - python

Is there a better way to get the row count than doing the following?
cursor.execute("SELECT DISTINCT(provider_id) FROM main_iteminstance")
num_items = len(cursor.fetchall())
Is there a shorthand in MySQLdb for the above?

You could execute the following SQL directly on cursor.execute rather than depending on MySQLdb:
cursor.execute("SELECT COUNT(DISTINCT provider_id) FROM main_iteminstance")
Then you just get the result from that query.

The result of cursor.execute returns the number of rows returned by the query so just assign to a variable.
num_items = cursor.execute("SELECT DISTINCT(provider_id) FROM main_iteminstance")
This will also work and you won't have to run an extra query just to get the number of items

Related

Is it possible to assign cursor.fetchall() to a variable?

rows_order = "SELECT COUNT (*) FROM 'Order'"
cursor.execute(rows_order)
ordernum = cursor.fetchall()
connection.commit()
cursor.execute("INSERT INTO 'Order' (OrderNo, CustomerID, Date, TotalCost) VALUES (?,?,?,?)", (
[ordernum], custid_Sorder, now, total_item_price))
This is what I am trying but this error popped up;
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.
How do I fix this? I want to make it so the OrderNo is = to the amount of orders before it, hence why I want to assign the orderno to it. (I am using sqlite3)
as you have only one value you need only fetchone
import sqlite3
con = sqlite3.connect("tutorial.db")
cursor = con.cursor()
rows_order = "SELECT COUNT (*) FROM 'Order'"
cursor.execute(rows_order)
ordernum = cursor.fetchone()[0]
cursor.execute("INSERT INTO 'Order' (OrderNo, CustomerID, Date, TotalCost) VALUES (?,?,?,?)", (
ordernum, custid_Sorder, now, total_item_price))
tl;dr Don't do this. Use an auto-incremented primary key.
fetchall returns all rows as a list, even if there is only one row.
Instead, use fetchone. This will return a single tuple which you can then select the first item. ordernum = cursor.fetchone()[0]
However, you appear to be writing a query to get the next ID. Using count(*) is wrong. If there are any gaps in OrderNo, for example if something gets deleted, it can return a duplicate. Consider [1, 3, 4]; count(*) will return 3. Use max(OrderNo) instead.
Furthermore, if you try to insert two orders at the same time you might get a race condition and one will try to duplicate the other.
process 1 process 2
select max(orderNo)
fetchone # 4
select max(orderNo)
fetchone # 4
insert into orders...
insert into orders... # duplicate OrderNo
To avoid this, you have to do both the select and insert in a transaction.
process 1 process 2
begin
select max(orderNo)...
fetchone # 4 begin
select max(orderNo)
fetchone
insert into orders... # wait
commit # wait
# 5
insert into orders...
commit
Better yet, do them as a single query.
insert into "Order" (OrderNo, CustomerID, Date, TotalCost)
select max(orderNo), ?, ?, ?
from "order"
Even better don't do it at all. There is a built-in mechanism to do this use an auto-incremented primary keys.
-- order is a keyword, pluralizing table names helps to avoid them
create table orders (
-- It is a special feature of SQLite that this will automatically be unique.
orderNo integer primary key
customerID int,
-- date is also a keyword, and vague. Use xAt.
orderedAt timestamp,
totalCost int
)
-- orderNo will automatically be set to a unique number
insert into orders (customerID, orderedAt, totalCost) values (...)

Python mysql fetchall() returns additional characters

I am trying to retrieve values from a table to use in a calculation. The code below
mycursor = mydb.cursor()
mycursor.execute("SELECT number FROM info")
rows = mycursor.fetchall()
print (rows)
This returns this list
[(Decimal('30.00'),), (Decimal('66.00'),), (Decimal('72.00'),)]
How can I retrieve the numerical value only either in a list or tuple like
[30.00, 66.00, 72.00]
The original data type in mydb might be a Decimal object.
So you can cast the datatype in the MySQL query or python code.
1) Case in MySQL:
SELECT CAST(number AS DOUBLE) FROM info
but this code returns the fetched rows as
[(30.00,), (66.00,), (72.00,)] because the tuples represent the columns of the query result.
2) Case in python code:
converted_rows = list(map(lambda row:float(row[0]), rows))
It will return [30.00, 66.00, 72.00] list.

Brief syntax for inserting row into sqlite database using python sqlite3

I have a csv file of size 360x120 that I want to import into my sqlite database row by row. For one row, I know that below syntax works if mytuple has 2 elements:
import sqlite3
conn = sqlite3.connect(dbLoc)
cur = conn.cursor()
mytuple = (a, b, c, ...) #some long tuple of 120 elements
cur.execute('INSERT INTO tablename VALUES (?, ?)', mytuple)
Problem is, my rows contain 120 columns and I can't really go type 120 question marks into the cur.execute() line. Actually I have, it works but yeah, it is not a good solution. One thing I have tried was:
cur.execute('INSERT INTO tablename VALUES ?', mytuple)
Thought it would just do ?=mytuple and replace ? with mytuple but it doesn't do that. A user comment on the article sebastianraschka.com/Articles/2014_sqlite_in_python_tutorial.html shows such syntax, which would work for me but it does not:
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
As seen here he's able to replace a tuple into the execute string with a single ? used. How can I achieve the same with INSERT INTO tablename?
sqlite3 doesn't support more concise syntax:
c.execute('INSERT INTO tablename VALUES ({}?)'.format('?,'*(len(t) - 1)), t)
Note: the default SQLITE_MAX_COLUMN is 2000. And some algorithms in SQLite are O(n**2) in the number of columns i.e., if you increase the limit; it may slow down db operations.

Why is `for...in` returning a tuple when trying to iterate through rows returned by query?

I select 1 column from a table in a database. I want to iterate through each of the results. Why is it when I do this it’s a tuple instead of a single value?
con = psycopg2.connect(…)
cur = con.cursor()
stmt = "SELECT DISTINCT inventory_pkg FROM {}.{} WHERE inventory_pkg IS NOT NULL;".format(schema, tableName)
cur.execute(stmt)
con.commit()
referenced = cur.fetchall()
for destTbl in referenced:#why is destTbl a single element tuple?
print('destTbl: '+str(referenced))
stmt = "SELECT attr_name, attr_rule FROM {}.{} WHERE ppm_table_name = {};".format(schema, tableName, destTbl)#this fails because the where clause gets messed up because ‘destTbl’ has a comma after it
cur.execute(stmt)
Because that's what the db api does: always returns a tuple for each row in the result.
It's pretty simple to refer to destTbl[0] wherever you need to.
Because you are getting rows from your database, and the API is being consistent.
If your query asked for * columns, or a specific number of columns that is greater than 1, you'd also need a tuple or list to hold those columns for each row.
In other words, just because you only have one column in this query doesn't mean the API suddenly will change what kind of object it returns to model a row.
Simply always treat a row as a sequence and use indexing or tuple assignment to get a specific value out. Use:
inventory_pkg = destTbl[0]
or
inventory_pkg, = destTbl
for example.

How to select second parameter from fetchall() in pyodbc

I am new in python so in the pyodbc. Maybe my question is very simple but I could not find any answer refer to my question.
I'm using this select
cursor.execute("SELECT [something] FROM [someone] WHERE [user_name]='John'")
rows = cursor.fetchall()
for row in rows:
print row.something
It prints some parameters for example 4 or 5.How to print only second or only third parameter.
I also used cursor.fetchmany() but I'm having same problem
If you wan't just the 4th row you can do:
rows = cursor.fetchall()
print rows[3].something
But it's better if you do it in the SQL query and avoid fetching all the rows from the database:
SELECT [something] FROM [someone] WHERE [user_name]='John' LIMIT 1 OFFSET 3
Example.
I guess your mean field and not parameter
cursor.execute("SELECT [something] FROM [someone] WHERE [user_name]='John'")
rows = cursor.fetchall()
from row in rows:
print row[1]

Categories

Resources