Using substitution in Pythhon with mysql cursor method - python

I have multiple databases named in a pattern. Database names,
for example: house_1, house_2, house_2
In my Python(2.7) script, a variable gets passed (house_id). That variable contains 1, 2 or 3, etc.
I need to be able to establish a connection to the appropriate database depending on the house_id.
Individually, this looks like:
house1_db = mysql.connector.connect(user="root", password="mypassword!", host="127.0.0.1", database="house_1")
cursor = house1_db.cursor
It seems really clumsy to me to do it this way. I'm looking for a way to do the equivalent of string substitution.
So, script gets passed house_id = 6
And then:
house%d_db = mysql.connector.connect(user="root", password="mypassword!", host="127.0.0.1", database="house_%d") % house_id
cursor = house%d_db.cursor % house_id
I know the above examples with %d are wrong. But I think it illustrates what I am trying to accomplish. Maybe not.
I've been playing around with string substitution mainly, and am getting errors like: "
String Object has no attribute cursor".
Thanks in advance. I know this is a vague question. I'm getting rather frustrated with it!

Create a function and pass db_name to it.
Using with closes your connection and cursor automatically.(No need to close it explicitly like conn.close(), cursor.close() )
Try this,
def create_conn(db_name):
return mysql.connector.connect(user="root", password="mypassword!", host="127.0.0.1", database=db_name)
with create_conn('house_1') as conn:
with conn.cursor() as cursor:
...

Related

sqlalchemy connection flask

I have the following code in flask
sql = text('select * from person')
results = self.db.engine.execute(sql)
for row in results:
print(".............", row) # prints nothing
people = Person.query.all() # shows all person data
Now given this situation, it's obvious, the self.db is not using the same connection somehow that Person.query is using. However, given this situation, can I get the connection somehow from Person.query object?
PS. This is for testing and I'm using SQLite3 database. I tried this in postgres, but outcome is the same.
Just figured out. Try Person.query.session.execute(sql). Voila!

Output parameters are not populated

I have the following code:
conn = pymssql.connect(server, user, password, database)
cursor = conn.cursor()
id_new_field = pymssql.output(int)
res = cursor.callproc('NewField', ('Test',id_new_field))
conn.commit()
conn.close()
print(id_new_field.value)
print(res)
Unfortunately my output parameter isn't populated with the id of the field, although the stored procedure is executed correctly. The output ist always 'None'.
I think the problem is, that autocommit ist set to false in my example, am i right?
But i can't set autocommit to true because the stored procedure is raising an error when it isn't executed inside a transaction (It's a vendor SP and i can't alter the SP).
So, my workarount for now is, to use .execute() instead of .callproc() and writing raw sql into my python script. It's awful. ;)
Is there any chance to use .callproc() with autocommit = false?
Or do i have to do it completely different?
I also got None when I did
print(id_new_field.value)
but I was able to retrieve the value by simply indexing into res tuple:
print(res[1])
(Tested with Python 2.7.11 and pymssql 2.1.1.)

stored proc not committing with sqlalchemy/pyodbc

I am using sqlalchemy/pyodbc to connect to a MS SQL 2012 server. I chose sqlalchemy because of the direct integration with pandas dataframes using .read_sql and .to_sql.
At a high level, my code is:
df = dataframe.read_sql("EXEC sp_getsomedata")
<do some stuff here>
finaldf.to_sql("loader_table", engine,...)
This part works great, very easy to read, etc. The problem is that I have to run a final stored proc to insert the data from the loader table into the live table. Normally, sqlalchemy knows to commit after INSERT/UPDATE/DELETE, but doesn't want to do the commit for me when I run this final stored proc.
After having tried multiple approaches, I see the transaction in the db sitting uncommitted. I know sqlalchemy is very flexible and I am using about 3% of its functionality, what is the simplest way to get this working? I think I need to be using sqlalchemy core and not ORM. I saw examples using sessionmaker, but I think that monopolizes the engine object and doesn't let pandas access it.
connection = engine.connect()
transaction = connection.begin()
connection.execute("EXEC sp_doLoaderStuff")
transaction.commit()
connection.close()
I have tried calling .execute from the connection level, from a cursor level, and even using the .raw_connection() method without success.
connection = engine.raw_connection()
connection.autocommit = True
cursor = connection.cursor()
cursor.execute("EXEC sp_doLoaderStuff")
connection.commit()
connection.close()
Any ideas what I am missing here?
Completely self-inflicted. The correct working code using the raw_connection() method that is working fine is:
connection = engine.raw_connection()
cursor = connection.cursor()
cursor.execute("EXEC sp_doLoaderStuff")
connection.commit()
connection.close()

Connector/python select after insert

I have a database table with UNIQUE key. If I want to insert some record there are two possible ways. First, the unique item doesn't exist yet, that's OK, just return new id. Second, the item already exists and I need to get the id of this unique record.
The problem is, that anything I try, I get always some exception.
Here's example of the code:
def __init__(self, host, user, password, database):
# set basic attributes
super().__init__(host, user, password, database)
#open connection
try:
self.__cnx = mysql.connector.connect(
database=database, user=user, password=password, host = host)
#self.__cursor = self.__cnx.cursor()
except ...
def insert_domain(self, domain):
insertq = "INSERT INTO `sp_domains` (`domain`) VALUES ('{0}')".format(domain)
cursor = self.__cnx.cursor()
try:
cursor.execute(insertq)
print("unique")
except (mysql.connector.errors.IntegrityError) as err:
self.__cnx.commit()
print("duplicate")
s = "SELECT `domain_id` FROM `sp_domains` WHERE `domain` = '{0}';".format(domain)
try:
id = cursor.execute(s).fetchone()[0]
except AttributeError as err:
print("Unable to execute the query:", err, file=sys.stderr)
except mysql.connector.errors.ProgrammingError as err:
print("Query syntax error:", err, file=sys.stderr)
else:
self.__cnx.commit()
cursor.close()
but anyting I try, on the first duplicate record I get either 'MySQL Connection not available', 'Unread result'. The code is just example to demonstrate it.
This is my first program using Connector/python, so I don't know all the rules, about fetch the results, commiting queries and so on.
Could anyone help me with this issue, please? Or is there any efficient way to such task ('cause this one seems to be not the best solution to me). Thank you for any advice.
I can't fix your code, because you've given us two different versions of the code and two partially-described errors without full information, but I can tell you how to get started.
From a comment:
In previous version it was type error I guess, something like "NoneType has no attribute 'fetchone'.
Looking at your code, the only place you call fetchone is here:
id = cursor.execute(s).fetchone()[0]
So obviously, cursor.execute(s) returned None. Why did it return None? Well, that's what it's supposed to return, according to the documentation.*
What you want to do is:
cursor.execute(s)
id = cursor.fetchone()[0]
… as all of the sample code does.
And for future reference, it's a lot easier to debug an error like this if you first note which line it happens on instead of throwing away the traceback, and then breaking that line into pieces and logging the intermediate values. Usually, you'll find one that isn't what you expected, and the problem will be much more obvious at that point, then three steps later on when you get a bizarre exceptions.
* Technically, the documentation just says that "Return values are not defined" for cursor.execute, so it would be perfectly legal for a DB-API module to return self here. Then again, it would also be legal to return some object that erases your hard drive when you call a method on it.

Fixing SQL Injection With _mysql

I just found out that the way I am using _mysql is causing a major SQL Injection problem.
My current code looks like:
db = _mysql.connect('', 'user', 'pass', 'db')
query = """SELECT * FROM stuff WHERE thing="{0}" """.format(user_input)
cur.query(query)
What am I doing wrong and how can I fix it so that it is safe?
I have tried using _mysql.escape_string() but that still returns an SQL syntax error.
You can use MySQLdb on its own:
conn = MySQLdb.connect();
curs = conn.cursor();
curs.execute("SELECT * FROM stuff WHERE thing = %s", (user_input));
If you want to stick with _mysql, use db.escape_string(user_input).
Documentation: http://mysql-python.sourceforge.net/MySQLdb.html
A nice handy reference is available via the bobby tables website.
You may also find value in In this powerpoint reference which shows some examples of sql injection as well as possible ways to mitigate the issue.

Categories

Resources