mysql.connector select query with binary values - python

Using Python's mysql.connector, how can I select all records that match a tuple?
For example:
ids = (b'6TRsHMzWSrq0zeembo0Vbg',
b'7Qoq53lKTk-RZOi830t3MA',
b'7ZGO9S3DTcGHjwrfpV0E0A')
And then the query would do something like:
query = SELECT first_name
FROM users
WHERE id = (ids)
Returning records for all users whose ID appears in the tuple

Try doing this
query = "SELECT first_name FROM users WHERE id IN " + str(list(ids))
cursor.execute(query)
On second thoughts, the following should also work
query = "SELECT first_name FROM users WHERE id IN " + str(ids)
EDIT
OP mentions in comments that the ids are binary data returned from a previous query. In which case, taking hint from this answer and using BINARY operator, the following query should work
query = "SELECT first_name FROM users WHERE BINARY id IN " + str(ids) ;

Related

how to insert values into user inputted column using pyodbc

im trying to insert values into a column that a user has asked to be changed which is called surnamereq and the user change which is called name1. money_spent is the name of the table and first_name is the column that the user is changing the value of.
This is how it should be written in SQL(i think):
INSERT INTO money_spent(first_name)
WHERE last_name = surnamereq
VALUES(name1)
This is what ive got in python:
cursor.execute("INSERT INTO money_spent(first_name) WHERE last_name = ?, surnamereq VALUES(name1)")
Thanks
The documentation for the .execute method shows that the form of the method call is
execute(sql, *parameters)
and states that
The optional parameters may be passed as a sequence, as specified by the DB API, or as individual values.
So, you could either do
surnamereq = 'Thompson'
fname = 'Gord'
#
sql = "UPDATE money_spent SET first_name = ? WHERE last_name = ?"
params = (fname, surnamereq)
cursor.execute(sql, params)
or
surnamereq = 'Thompson'
fname = 'Gord'
#
sql = "UPDATE money_spent SET first_name = ? WHERE last_name = ?"
cursor.execute(sql, fname, surnamereq)
Note that the second approach is a pyodbc-specific extension to the DB API.

Python SQLite3 query concatenating two values

I have a database (student.db) that contains one table (Students).
Each row in students contains (ID, FName, LName).
There is an existing row (0, John, Doe).
I want to be able to enter a variable as a full name, find that name in the database, and delete that row.
Here's what I came up with... but it doesn't seem to work:
import sqlite3
conn = sqlite3.connect('student.db')
c = conn.cursor()
selection = "John Doe"
c.execute('DELETE FROM Students WHERE (FName + " " + LName =?', (selection,))
I don't get an error message. I'm guessing that's because it simply doesn't find any entries that match the WHERE clause.
Is there a way to properly write a WHERE clause that incorporates multiple values from the row of interest?
I am very new to this, so I apologize if this is a dumb question. I'm trying to make a Kivy app that creates a ListView of student names. Then you can select a student from the list and click "Delete" to remove that student from the ListView dictionary and from the database.
For concatenation most SQL implementations use '||' operator. See SQLite docs.
c.execute("DELETE FROM Students WHERE (FName || ' ' || LName = ?", (selection,))
Working with names is difficult but I think I'm over-thinking your question. Assuming that you just want to query two fields, you can split the name into a first_name and a last_name, and delete from the DB where that combination is satisfied.
selection = "John Doe"
first_name, last_name = selection.split()
query = """
DELETE FROM Students
WHERE FName = ? AND LName = ?
"""
c.execute(query, (first_name, last_name))
conn.commit()

Trying to search a column on SQLite Python so that it only returns the information searched

New to Python and Databases
I have a database table set up with a column of usernames. I want the user to be able to search through the table via a raw_input and only return the values which are associated with that user name.
E.g. user searches for Bill and it only displays Bill's records ordered by a specified column
This is what I have so far but its obviously VERY wrong, hope someone can help:
def find_me(db, column_name):
db = sqlite3.connect(db)
cursor = db.cursor()
name = raw_input("Please enter your username: ")
cursor.execute("SELECT name FROM username WHERE name=?", (name,))
cursor.execute("SELECT * FROM username ORDER BY "+column_name+" ASC")
name = cursor.fetchone()
next = cursor.fetchone()
Thank you in advance
You want to make the query similar to the following:
cursor.execute("SELECT name FROM username WHERE name=?", (name,))
This uses query parameters, so it's correctly escaped for the data provided. Then just adapt this to SELECT * and whatever else you want from the result.
Try working with this:
name = raw_input("Please enter your username: ")
query = "SELECT * FROM username WHERE name=? ORDER BY {0}".format(column_name)
cursor.execute(query, (name,))
for row in cursor:
print row

Getting the id of the last record inserted for Postgresql SERIAL KEY with Python

I am using SQLAlchemy without the ORM, i.e. using hand-crafted SQL statements to directly interact with the backend database. I am using PG as my backend database (psycopg2 as DB driver) in this instance - I don't know if that affects the answer.
I have statements like this,for brevity, assume that conn is a valid connection to the database:
conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
Assume also that the user table consists of the columns (id [SERIAL PRIMARY KEY], name, country_id)
How may I obtain the id of the new user, ideally, without hitting the database again?
You might be able to use the RETURNING clause of the INSERT statement like this:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING *")
If you only want the resulting id:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING id")
[new_id] = result.fetchone()
User lastrowid
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
result.lastrowid
Current SQLAlchemy documentation suggests
result.inserted_primary_key should work!
Python + SQLAlchemy
after commit, you get the primary_key column id (autoincremeted) updated in your object.
db.session.add(new_usr)
db.session.commit() #will insert the new_usr data into database AND retrieve id
idd = new_usr.usrID # usrID is the autoincremented primary_key column.
return jsonify(idd),201 #usrID = 12, correct id from table User in Database.
this question has been asked many times on stackoverflow and no answer I have seen is comprehensive. Googling 'sqlalchemy insert get id of new row' brings up a lot of them.
There are three levels to SQLAlchemy.
Top: the ORM.
Middle: Database abstraction (DBA) with Table classes etc.
Bottom: SQL using the text function.
To an OO programmer the ORM level looks natural, but to a database programmer it looks ugly and the ORM gets in the way. The DBA layer is an OK compromise. The SQL layer looks natural to database programmers and would look alien to an OO-only programmer.
Each level has it own syntax, similar but different enough to be frustrating. On top of this there is almost too much documentation online, very hard to find the answer.
I will describe how to get the inserted id AT THE SQL LAYER for the RDBMS I use.
Table: User(user_id integer primary autoincrement key, user_name string)
conn: Is a Connection obtained within SQLAlchemy to the DBMS you are using.
SQLite
======
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
# Execute within a transaction (optional)
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.lastrowid
txn.commit()
MS SQL Server
=============
insstmt = text(
'''INSERT INTO user (user_name)
OUTPUT inserted.record_id
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
MariaDB/MySQL
=============
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = conn.execute(text('SELECT LAST_INSERT_ID()')).fetchone()[0]
txn.commit()
Postgres
========
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm)
RETURNING user_id ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
result.inserted_primary_key
Worked for me. The only thing to note is that this returns a list that contains that last_insert_id.
Make sure you use fetchrow/fetch to receive the returning object
insert_stmt = user.insert().values(name="homer", country_id="123").returning(user.c.id)
row_id = await conn.fetchrow(insert_stmt)
For Postgress inserts from python code is simple to use "RETURNING" keyword with the "col_id" (name of the column which you want to get the last inserted row id) in insert statement at end
syntax -
from sqlalchemy import create_engine
conn_string = "postgresql://USERNAME:PSWD#HOSTNAME/DATABASE_NAME"
db = create_engine(conn_string)
conn = db.connect()
INSERT INTO emp_table (col_id, Name ,Age)
VALUES(3,'xyz',30) RETURNING col_id;
or
(if col_id column is auto increment)
insert_sql = (INSERT INTO emp_table (Name ,Age)
VALUES('xyz',30) RETURNING col_id;)
result = conn.execute(insert_sql)
[last_row_id] = result.fetchone()
print(last_row_id)
#output = 3
ex -

Python String Formats with SQL Wildcards and LIKE

I'm having a hard time getting some sql in python to correctly go through MySQLdb. It's pythons string formatting that is killing me.
My sql statement is using the LIKE keyword with wildcards. I've tried a number of different things in Python. The problem is once I get one of them working, there's a line of code in MySQLdb that burps on string format.
Attempt 1:
"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN
tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query)
This is a no go. I get value error:
ValueError: unsupported format character ''' (0x27) at index 128
Attempt 2:
"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN
tag ON user.id = tag.userId WHERE user.username LIKE '\%%s\%'" %
(query)
I get the same result from attempt 1.
Attempt 3:
like = "LIKE '%" + str(query) + "%'" totalq = "SELECT tag.userId,
count(user.id) as totalRows FROM user INNER JOIN tag ON user.id =
tag.userId WHERE user.username " + like
This correctly creates the totalq variable, but now when I go to run the query I get errors from MySQLdb:
File "build/bdist.macosx-10.6-universal/egg/MySQLdb/cursors.py", line
158, in execute query = query % db.literal(args) TypeError: not enough
arguments for format string
Attempt 4:
like = "LIKE '\%" + str(query) + "\%'" totalq = "SELECT tag.userId,
count(user.id) as totalRows FROM user INNER JOIN tag ON user.id =
tag.userId WHERE user.username " + like
This is the same output as attempt 3.
This all seems really strange. How can I use wildcards in sql statements with python?
Those queries all appear to be vulnerable to SQL injection attacks.
Try something like this instead:
curs.execute("""SELECT tag.userId, count(user.id) as totalRows
FROM user
INNER JOIN tag ON user.id = tag.userId
WHERE user.username LIKE %s""", ('%' + query + '%',))
Where there are two arguments being passed to execute().
It's not about string formatting but the problem is how queries should be executed according to db operations requirements in Python (PEP 249)
try something like this:
sql = "SELECT column FROM table WHERE col1=%s AND col2=%s"
params = (col1_value, col2_value)
cursor.execute(sql, params)
here are some examples for psycog2 where you have some explanations that should also be valid for mysql (mysqldb also follows PEP249 dba api guidance 2.0: here are examples for mysqldb)
To escape ampersands in Python string formatting expressions, double the ampersand:
'%%%s%%' % search_string
Edit: But I definitely agree with another answer. Direct string substitution in SQL queries is almost always a bad idea.
import mysql.connector
mydatabase = mysql.connector.connect(host="localhost", user="root", passwd="1234", database="databaseName")
mycursor = mydatabase.cursor()
user_input =[]
item = str("s%")
user_input.append(item)
mycursor.execute("SELECT * FROM employees WHERE FIRST_NAME LIKE %s ESCAPE ''",user_input )
result = mycursor.fetchall()
for row in enumerate(result):
print(row)
I used the following and it worked:
my_str = 'abc'
query = f"""select * from my_table where column_a like '%%{my_str}%%' """
df=pandas.read_sql_query(query, engine)
We could try escaping the percentage character by doubling them like this:
query_to_get_user_name = """
SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag
ON user.id = tag.userId
WHERE user.username LIKE '%%%s%%' """ % (user_name,)
cursor.execute(query_to_get_user_name)
So I tried this and I think I have got the answer which is simpler for me to understand , a school student .
In my code the table name is "books" and the column I'm Searching for is "Name".
If you need more xplaination , then feel free to drop a mail at dhruv2003.joshi#gmail.com and I will try my best to answer ASAP
def S():
n=str(input('Enter the name of the book: '))
name='%'+n+'%'
NAME=name
query="select * from books where Name like '"+NAME+"' "
c.execute(query)
ans=c.fetchall()
if len(ans)>0:
print('')
for i in ans:
print(i)
print('')
else:
print('')
print('An error occured')
print('Name you gave does not exist :( ')
print('')
I have a solution to your problem :
You can not use :
"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query)
you can change it with string template, such as :
import MySQLdb
import string # string module
.......
value = {'user':'your value'}
sql_template = string.Template("""
SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN
tag ON user.id = tag.userId WHERE user.username LIKE '%$user%'
""")
sql = sql_template.substitute(value)
try:
cursor.execute(sql)
...........
except:
...........
finally :
db.close()

Categories