I'm relatively new at Python but have more experience in Java, so I understand most of the concepts. However, I keep having issues with MySQL and passing information back from a function using MySQL
to use in another function later.
I need to make complex MySQL queries with multiple return field, So I don't want to be running multiple SQL queries for each SQL field as this will smash the database.
Saying that the below is a small example of what I'm trying to achieve.
I wanted a function to run an SQL query (def connectory_mysql()) that took parameters from elsewhere, (this part works) then take the output of the SQL query and pass back to the main function to use.
The main function then needs to use the different column results of the SQL query for different parameters.
I can return the result and assign it to a result1 which appears and looks like a dictionary when printed, but I'm unable to split/use the different keys or data from the result1 = connector_mysql(subSerialNum, ldev, today_date)
If i splituse the keys in the dictionary in the SQL function before returning ie ldev_cap = result['ldev_cap']
I can print the individual elements within the SQL function... However, I cant seem to pass the parameters then back to the main function and split them out??
I must have missed something easy or am not understanding something... any assistance or help would be greatly appreciated...
...
result1 = connector_mysql(subSerialNum, ldev, today_date)
print(result1) #this works and appears to be a dictionary, but I can split it
## into its elements like:
ldev_cap = result1['ldev_cap'] ##-> this dosn't work here.....???? if i return it as a dictonary..
#and i'm unsure how to split them when i pass just the paramaters
#back if i split the dictionary in the sql function.
...
def connector_mysql(subSerialNum, ldev, today_date):
import pymysql.cursors
db_server = 'localhost'
db_name = 'CBDB'
db_pass = 'secure_password'
db_user = 'user1'
sql_query = (
"SELECT ldev_cap, ldev_usdcap FROM Ldevs WHERE sub_serial=%(serial)s "
"and ldev_id=%(lun)s and data_date=%(todayD)s")
connection = pymysql.connect(host=db_server,
user=db_user,
password=db_pass,
db=db_name,
cursorclass=pymysql.cursors.DictCursor)
try:
with connection.cursor() as cursor:
cursor.execute(sql_query, {'serial': subSerialNum, 'lun': ldev, 'todayD': today_date})
result = cursor.fetchone()
while result:
ldev_cap = result['ldev_cap'] #here the dictionary acts as
#expected and i can assign a value
ldev_usdcap = result['ldev_usdcap']
print(result)
return ldev_cap, ldev_usdcap #here i can return
finally:
connection.close()
Any help or assistance would be greatly apricated...
Cheers
Graham
First of all, you should get familiar with the Python style guide for writing python code.
Based on your existing code, result1 return as a tuple that contained the value of (ldev_cap, ldef_usdcap) (it is not a directory). You get access to the return result as result1[0] which corresponding to the return value of ldev_cap or result1[1] which corresponding to the return value of ldev_usdcap.
Alternatively, since you are returning two data, you can access each return data by using
ldev_cap, ldev_usdcap = connector_mysql(subSerialNum, ldev, today_date)
Related
this should be pretty simple.
I'm writing a program to pull data from a database to be stored in a variable and passed on to another program. I have it working to connect to the db and run the query to pull the data, which is returned in a new line for each column. I would like to parse through this output to store only the columns I need into separate variables to be imported by another python program. Please note that the print(outbound) part is just there for testing purposes.
Here's the function:
def pullData():
cnxn = pyodbc.connect('UID='+dbUser+';PWD='+dbPassword+';DSN='+dbHost)
cursor = cnxn.cursor()
#run query to pull the newest sms message
outbound = cursor.execute("SELECT * FROM WKM_SMS_outbound ORDER BY id DESC")
table = cursor.fetchone()
for outbound in table:
print(outbound)
#close connection
cnxn.close()
and here's the sample output from the query that I would like to parse through- as it's currently being stored in variable outbound. (NOTE) This is not 1 column. This is one ROW. Each new line is a new column in the db... this is just how it's being returned and formatted when I run the program.
I think this is the best way you can achieve this:
(Considering that your table variable returns as list)
# Lets say until here you've done your queries
collection = {}
for index,outbound in enumerate(table):
key_name = "key{0}".format(index)
collection[key_name] = outbound
print(collection)
OUTPUT Expected:
{
"key1" : 6932921,
"key2" : 303794,
...
...
...
}
And then what you can do to access it from another python file by importing the collection variable by adding return collection on your pulldata function
On the other python file it will be simple just to:
from your_file_name import collection # considering they are on the same directory
I'm using python in TestComplete to conduct a db query, but the results seem to be empty strings and do not match the data in the table I queried. The file is a s3db file. Does that matter?
Using:
TestComplete Version 14
imported sqlite3 into python file
I've:
-Tried running the same query in SQLite. It returned the expected result
-Verified the connection is established with the correct db
---python
import sqlite3
def getInfo():
conn = sqlite3.connect(db)
c = conn.cursor()
try:
c.execute('SELECT Column_Name FROM Table_Name')
results = c.fetchall()
except:
Log.Error("Query execution failed")
for x in results:
Log.Message(x) `enter code here`
#Log.Message() works like a print statement in testcomplete.
---
Actual Output:
The program runs without errors, but the results come back as 15 lines of blank rows. 15 is the number of records within the table, so I know it's looking in the right place, but it seems like it's not identifying that there's information stored here.
Expected Output:
15 lines of data contained within the Column I specified in the query.
There is no error with sqlite3 and your DB operations. The issue is with Log.Message and what it expects as an argument. Within TestComplete, Log.Message requires variable arguments of type Variant, which can be any of the supported data types within TestComplete; String, Double/Real, Boolean, Date/Time, Object (i.e. TestComplete-recognised UI objects) and Integer.
Log.Message cannot accept arguments of the type returned by cursor.fetchall's rows.
So you'd need to convert each row into a String, e.g.
for x in results:
msg = ('{0} : {1}'.format(x[0], x[1]))
Log.Message(msg)
I am aware that queries in Python can be parameterized using either ? or %s in execute query here or here
However I have some long query that would use some constant variable defined at the beginning of the query
Set #my_const = 'xyz';
select #my_const;
-- Query that use #my_const 40 times
select ... coalesce(field1, #my_const), case(.. then #my_const)...
I would like to do the least modif possible to the query from Mysql. So that instead of modifying the query to
pd.read_sql(select ... coalesce(field1, %s), case(.. then %s)... , [my_const, my_const, my_const, ..]
,I could write something along the line of the initial query. Upon trying the following, however, I am getting a TypeError: 'NoneType' object is not iterable
query_str = "Set #null_val = \'\'; "\
" select #null_val"
erpur_df = pd.read_sql(query_str, con = db)
Any idea how to use the original variable defined in Mysql query ?
The reason
query_str = "Set #null_val = \'\'; "\
" select #null_val"
erpur_df = pd.read_sql(query_str, con = db)
throws that exception is because all you are doing is setting null_value to '' and then selecting that '' - what exactly would you have expected that to give you? EDIT read_sql only seems to execute one query at a time, and as the first query returns no rows it results in that exception.
If you split them in to two calls to read_sql then it will in fact return you the value of your #null value in the second call. Due to this behaviour read_sql is clearly not a good way to do this. I strongly suggest you use one of my suggestions below.
Why are you wanting to set the variable in the SQL using '#' anyway?
You could try using the .format style of string formatting.
Like so:
query_str = "select ... coalesce(field1, {c}), case(.. then {c})...".format(c=my_const)
pd.read_sql(query_str)
Just remember that if you do it this way and your my_const is a user input then you will need to sanitize it manually to prevent SQL injection.
Another possibility is using a dict of params like so:
query_str = "select ... coalesce(field1, %(my_const)s, case(.. then %(my_const)s)..."
pd.read_sql(query_str, params={'my_const': const_value})
However this is dependent on which database driver you use.
From the pandas.read_sql docs:
Check your database driver documentation for which of the five syntax
styles, described in PEP 249’s paramstyle, is supported. Eg. for
psycopg2, uses %(name)s so use params={‘name’ : ‘value’}
just to explain whats going here: I have a search function that runs a MySQL query using user input [givenLocation]. It is supposed to dump the contents of the query into the listbox [self.lookuplist]. My issue is that currently it will only dump the first result even though I am using the fetchall() function. I am a self-taught python developer but I have not been able to find any information on this from other sources. Here is my code:
def searchL_button(self):
i = 0
givenLocation = self.top3.searchEntry1.get()
searchLookup = ("SELECT Status, Serial, Product_Code, Location FROM Registers WHERE Location = %s")
cursor9.execute(searchLookup, [givenLocation])
locRes = cursor9.fetchall() [i]
for i in locRes:
self.lookupList.insert(END, locRes)
You are setting the variable locRes to only contain the first result of your query. Change the last few lines to the following
locRes = cursor9.fetchall()
for curRes in locRes:
self.lookupList.insert(END, curRes)
I am trying to find out if a value is present in a column in a MySQL table from my django application. This is what I have done:
cursor = connection.cursor()
cursor.execute('SELECT COUNT(*) FROM model_combination_bank WHERE combination = %s AND validity = 1', [combination])
result = cursor.fetchall
if result != 1:
self.respond('Sorry. The entry code you entered is not valid. Please try again with a valid code.')
return()
I know for sure that there is a 1 row in the table that matches the SELECT STATEMENT but the self.respond function runs. Can somebody kindly tell me whats wrong with my code.
You didn't call the method:
result = cursor.fetchall()
However you shouldn't really be using raw SQL here. Use the model layer:
result = ModelCombinationBank.objects.filter(validity=1, combination=combination).count()
assuming your model is called ModelCombinationBank. And if all you need to is to check that the combination exists, use exists() instead of count(), since that is a cheaper query.
Another way to see if a value exists and do something if it does:
try:
obj = ModelCombinationBank.objects.get(validity=1, combination=combination)
# do something with obj
except ModelCombinationBank.DoesNotExist:
# do something if not found