I'm learning programming with python and trying to implement the safest possible MySQL queries starting with the simple SELECT ones. The problem is whenever I use coma in a query I got the following error:
cursor.execute(query)
File "C:\Users\username\AppData\Local\Programs\Python\Python37-32\lib\site-packages\mysql\connector\cursor.py", line 536, in execute
stmt = operation.encode(self._connection.python_charset)
AttributeError: 'tuple' object has no attribute 'encode'
I am aware of the fact that coma itself isn't a source of a problem but I tried many different MySQL syntax and everytime I use a come I got this "AttributeError: 'tuple' object has no attribute 'encode'" error.
I also tried to change MySQL database encoding - nothing changes. The code is below.
import mysql.connector
conn = mysql.connector.connect(
charset='utf8',
# init_command='SET NAMES UTF8',
host="10.0.0.234",
user="x",
passwd="x>",
database="x",
)
print(conn.is_connected())
param = "test"
cursor = conn.cursor()
# =========== query below does work ========
# query = ("SELECT * from list WHERE username LIKE '%test%'")
# ============ query below does work =======
# query = ("SELECT * from list HAVING username = '%s'" % param)
# ============ query below doesn't work =====
# query = ("SELECT * from list HAVING username = %s", (param,))
# ============= query below doesn't work =====
query = "SELECT * from list WHERE username = :name", {'name': param}
cursor.execute(query)
result = cursor.fetchall()
for x in result:
print(x)
conn.close()
Any ideas what am I doing wrong?
The answer is a little bit tricky, but it is in essence because of what the actual value of the 'query' variable is...
For example:
# 1.
query = ("SELECT * from list WHERE username LIKE '%test%'")
# when you do this, query is a string variable,
# NB: the parentheses are not necessary here
# so when you call
cursor.execute(query)
# the value passed into the execute call is the string "SELECT * from list WHERE username LIKE '%test%'"
# 2.
query = ("SELECT * from list HAVING username = '%s'" % param)
# when you do this, query is the result of a string formatting operation
# This is a Python 2 form of string formatting
# The discussion here probably makes it more clear:
# https://stackoverflow.com/questions/13945749/string-formatting-in-python-3
# it is almost the same as doing this:
query = "SELECT * from list HAVING username = 'test'"
# so when you call
cursor.execute(query)
# the value passed into the execute call is the string "SELECT * from list HAVING username = 'test'"
# 3.
query = ("SELECT * from list HAVING username = %s", (param,))
# This operation is assigning a 2-value tuple into the query variable
# The first value in the tuple is the string "SELECT * from list HAVING username = %s"
# The second value in the tuple is a 1-value, with 'test' as its first value
# 4.
query = "SELECT * from list WHERE username = :name", {'name': param}
# This is similar to #3, but the values in the tuple are instead
# query[0] == "SELECT * from list WHERE username = :name"
# query[1] is a dictionary: {'name': param}
Both 3 and 4 above are not calling the MySQL execute with the parameters you are expecting (see API here). You probably need to do one of:
unpack the query tuple into separate variables, and call the function with them
operation, params = query # unpack the first elem into operation, and second into params
cursor.execute(operation, params)
just index into the query tuple
cursor.execute(query[0], query[1])
# NB: you could also use the 'named parameters' feature in Python
cursor.execute(query[0], params=query[1])
Use the 'unpacking arguments list' (SPLAT operator)
cursor.execute(*query)
Related
I have a following sql query:
SELECT *
FROM %s.tableA
The tableA is in db-jablonec so I need to call db-jablonec.tableA.
I use this method in Python:
def my_method(self, expedice):
self.cursor = self.connection.cursor()
query = """
SELECT *
FROM %s.tableA
"""
self.cursor.execute(query, [expedice])
df = pd.DataFrame(self.cursor.fetchall())
I call it like this:
expedice = ["db-jablonec"]
for exp in expedice:
df = db.my_method(exp)
But I got an error MySQLdb.ProgrammingError: (1146, "Table ''db-jablonec'.tableA' doesn't exist")
Obviously, I want to call 'db-jablonec.tableA' not ''db-jablonec'.tableA'. How can I fix it please?
It is passing %s as its own string including the quotes ''
you therefore need to pass it as one variable. Concatenate .table to the variable itself then pass it in.
Your query will therefore then be
query = """
SELECT *
FROM %s
"""
I think this will helpful for you
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%%'
Refer This.
I use this code:
I want to place the value in the SQL command via the% s operator, but when I reference the change value with% s, the command does not work:
s='amiravira.ir'
q1 = "SELECT DISTINCT name_cat FROM all_user WHERE id='%s' "
mycursor = mydb.cursor()
mycursor.execute( q1 ,s)
myresult = mycursor.fetchall()
myresult
The value can be found only if I write the SQL command line itself.
This is exactly the end of my project and it's really weird. I do not know why this happens:
q1 = "SELECT DISTINCT name_cat FROM all_user WHERE id = 'amiravira.ir'"
mycursor = mydb.cursor ()
mycursor.execute (q1, s)
myresult = mycursor.fetchall ()
myresult
I want to know what should I do to send data via SQL statements?
The argument(s) for the execute-call must be passed as an iterable (tuple or list), even if there's only one.
So write instead:
mycursor.execute(q1, (s,))
to pass the argument as an one element tuple.
I am trying to create a command line tool that generates a random string(password) of a given length, stores it in a sql db, and can be queried by name. The password generation and storing of it's output by a given name works beautifully, but trying to select only the password element is giving me trouble. I was able to select all from the table but that returns the name and the password. I only want the password returned. I thought about just splicing the output or even using the linux cut command, but I'd rather just get it from the select statement. Is this possible? My current SELECT statement returns: operation parameter must be a str. When I try it without the call to (name) at the end of the SELECT statement like this: query_password = """SELECT * FROM password_table WHERE name = ?"""
I get this error:
File "passbox.py", line 44, in <module>
query_pswd_by_name(name)
File "passbox.py", line 39, in query_pswd_by_name
c.execute(query_password)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 0 supplied.
BTW I'm sure my query_pswd_by_name function is all wrong, I've been experimenting. When I just create a connection and SELECT statement outside of a function it does return the name and password.
Also note that I've disguised my database file's name with asterisks for the purpose of this post. I am using an actual working db file in practice.
Here is all the code I've written so far:
import secrets
import string
import sqlite3
#CREATE PASSWORD OF GIVEN LENGTH
def get_pass(length):
return "".join(secrets.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits + string.punctuation) for x in range(length))
length = int(input("Enter the length of password: "))
password= get_pass(length)
print(password)
name = str(input("Enter name for password: "))
#CREATE DATABASE CONNECTION
conn = sqlite3.connect("****.db")
#CREATE CURSOR OBJECT
c = conn.cursor()
#CREATE TABLE IN DISK FILE BASED DATABASE
c.execute("""CREATE TABLE IF NOT EXISTS password_table (
name TEXT,
pswd TEXT
)""")
c.execute("INSERT INTO password_table (name, pswd) VALUES (?, ?)", (name, password))
#COMMIT CHANGES
conn.commit()
conn.close()
def query_pswd_by_name(name):
conn = sqlite3.connect('****.db')
c = conn.cursor()
query_password = """SELECT * FROM password_table WHERE name = ?""", (name)
c.execute(query_password)
result = c.fetchall()
for row in result:
print(row[1])
conn.commit()
query_pswd_by_name(name)
#CLOSE CONNECTION
conn.close()```
You need to break up the argument to the execute call.
c.execute(*query_password)
Or
c.execute("""SELECT * FROM password_table WHERE name = ?""", (name))
When running a query to a mysql database using MySqlHook, cursor.execute(query) returns int 1
My code is
import logging
from airflow.hooks.mysql_hook import MySqlHook
query = "SELECT col1, col2 FROM myschema.mytable LIMIT 1"
mysql = MySqlHook(mysql_conn_id=conn_id)
conn = mysql.get_conn()
cursor = conn.cursor()
result_cursor = cursor.execute(query)
logging.info(result_cursor) # this prints out "INFO - 1" in the log
df = pd.DataFrame(result_cursor.fetchall(), columns=result_cursor.keys()) # this triggers error "ERROR - 'int' object has no attribute 'fetchall'"
I would have expected result_cursor to return a "fetchable" result, since the query is working fine.
Cursor.execute() return value is not defined by the db-api spec, but for most implementations it returns the number of rows affected by the query.
To retrieve data, you have to either iterate over the cursor or call .fetchall().
It seems I cannot save cursor.execute(query) into variable result_cursor.
To make the code work, I simply needed to define the data for the data-frame as cursor.fetchall()
cursor.execute(query)
df = pd.DataFrame(list(cursor.fetchall()), column=[col[0] for col in cursor.description])
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.