How can I retrieve elements from an IBMdb2 database? - python

This is my current code
email = request.args.get('email')
password = request.args.get('password')
sql = 'SELECT email, senha FROM usuarios WHERE email = ?'
stmt = ibm_db.prepare(conn, sql)
param = email
email = ibm_db.fetch_assoc(stmt, param)
print(email)
It always returns an error and I can't get the values I need from my db2 database. What should I do to make it work?
my error code is
line 29, in login
email = ibm_db.fetch_assoc(stmt)
Exception: Fetch Failure: [IBM][CLI Driver] CLI0125E Function sequence error. SQLSTATE=HY010 SQLCODE=-99999

The code in the question missed out required steps:
ibm_db.bind_param() to give a value to the parameter marker
ibm_db.execute() to execute the prepared statement with the bound value
When there is an unexpected sequence (for example a missing API, in this case a fetch before any previous execute) then the driver will return CLI0125E (function sequence error).
Example code is in the Db2 documentation and many other places online.
It is wise to use exception handlers ( a try: ... except: block) in the code to catch and handle errors.

Related

Error inserting new registers on MySQL DB with Flask

I am looking for your help because i am getting this error on Python Flask:
pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Autoevaluacion', 'RT_Funcionarios', 'Reporteadores', 'Reporteadores_Gerentes', '' at line 1")
I am inserting data from Angular in my MySQL DB with the help of Flask, i am trying to insert the fields name, email, role and foros, this last one is filled with the elements of an array so when i tried to save the data, that error is shown.
this is my python code
#app.route('/insertarUsuario', methods = ["POST"])
def insertar_usuario():
conection = pymysql.connect('localhost', 'root','root', 'users')
data = request.json
print(data)
print(data['foros'])
cursor = conection.cursor()
sql_query ="INSERT INTO administrador_usuarios(nombre, email, rol, foros) VALUES ('" + str(data["nombre"]) + "','"+ str(data["email"])+"','"+str(data["rol"])+"', '"+ str(data["foros"])+"')"
cursor.execute(sql_query)
conection.commit()
response = "OK"
print("respuesta:",response)
return jsonify(response)
I would like to highlight 2 things:
1-. that array that will fill the field foros, it comes from the number of foros you select through checkboxes, so if i just check one, the register is saved but if i checked more than one, it crashes.
2-. i found out that if i replace
(data["foros"])
for
str("autoevaluacion" + "rt_funcionario")
it works so i think maybe it about how do i receive the array.
Can you help me please?. I am kinda new on Flask

MySQL python connector: "not all arguments converted during bytes formatting"

I have a mysql database in which 'user' table having f_name,l_name,password email(pk) by which session is created and table 'friendgroup' having fg_name(pk), email((pk),users.email(FK)) and table 'member' having email(pk,user.email(fk)), owner_email(pk,friendgroup.email(fk)), fg_name(pk,friendgroup.fg_name(fk)), and a python flask file below.
After login account, I wish to add a friend in chat. I tried to fix it from session['email']
def add_friend():
user = session['email']
friendgroups = _get_own_friendgroups(user) return
render_template('addFriend.html', friendgroups=friendgroups)
def _get_own_friendgroups(user):
cursor = mysql.connection.cursor()
#find all friendgroups that the user owns
find_owned_friendgroups = 'SELECT fg_name, description FROM friendgroup WHERE owner_email = %s ORDER BY fg_name ASC'
cursor.execute(find_owned_friendgroups, (user))
owned_friendgroups = cursor.fetchall()
cursor.close()
return owned_friendgroups
I expect output will be an open window and actively use of add friend when needed but showing error:
MySQLdb._exceptions.ProgrammingError: not all arguments converted during bytes formatting
A common error in python is to use (bar) instead of (bar,) the former not being a tuple.
Try with:
cursor.execute(find_owned_friendgroups, (user,))

pyodbc.ProgrammingError: No results. Previous SQL was not a query, when executing multiple statements at once

i am dealing with sql server database,
where i have a table named 'table1' containing 1 column and 1 row
exp_num
0
I am trying to update the 0 value exp_num column to +1 and also return old experiment and updated experiment.
For this i am using declare statements.
DECLARE #UpdateOutput1 table (Oldexp_num int,Newexp_num int);
UPDATE get_exp_num
SET exp_num = exp_num+1
OUTPUT
DELETED.exp_num,
INSERTED.exp_num
INTO #UpdateOutput1;
select * from #UpdateOutput1
When i'm running this in SQL editor i am getting the results.
Oldexp_num Newexp_num
0 1
but if i make this same as a query, and try to use pyodbc package i am getting error.
import pyodbc
connection = pyodbc.connect() # i am getting a connection
query = "DECLARE #UpdateOutput1 table (Oldexp_num int,Newexp_num int);UPDATE get_exp_num SET exp_num = exp_num+1 OUTPUT DELETED.exp_num, INSERTED.exp_num INTO #UpdateOutput1; select Newexp_num from #UpdateOutput1;"
cursor = connection.cursor()
cursor.execute(query)
cursor.fetchone()
When im doing cursor.fetchone() , i am getting following error.
File "<ipython-input-1398-bdaba305080c>", line 1, in <module>
cursor.fetchone()
ProgrammingError: No results. Previous SQL was not a query.
Is there any error in pyodbc package? or in my query
The problem was solved by adding SET NOCOUNT ON; to the beginning of the anonymous code block. That statement suppresses the record count values generated by DML statements like UPDATE ... and allows the result set to be retrieved directly.
Whenever the server generates some informative messages this scenario may occur. The thing is that pyodbc is not ready to handle multiple result sets at the same time that it is receiving "messages" from the server. By setting "NOCOUNT ON/OFF" you may get rid of just one kind of this "messages". The server could also yield some warnings or some procedure may PRINT something and those would "break" the SQL provoking the same error.
So a more generalist solution would be to iterate over the result sets while also checking if there are more sets to retrieve and inspecting if the server has sent any messages in between. For instance:
def process_query(self, query):
try:
self.cursor.execute(query)
rowlist = []
rows = self.__extract_resultset()
while rows or self.__has_next():
if rows:
rowlist.append(rows)
rows = self.__extract_resultset()
self.cursor.commit()
return rowlist
except pyodbc.ProgrammingError as e:
raise CustomException()
except Exception as e:
raise CustomException()
def __has_next(self):
try:
has_next = self.cursor.nextset()
if self.cursor.messages:
print(f'Info Message: {self.cursor.messages}', 'info')
except pyodbc.ProgrammingError as err:
has_next = False
print(f'ProgrammingError: {err}', 'error')
return has_next
def __extract_resultset(self):
data = []
try:
records = self.cursor.fetchall()
headers = [x[0] for x in self.cursor.description]
for record in records:
data.append(dict(zip(headers, record)))
except pyodbc.ProgrammingError as err:
print(f'ProgrammingError: {err}', 'error')
return data
Also some exception handling is more likely to be mandatory since both cursor.fetchall() and cursor.nextset() are very prone to fail because we don't know before hand when a message from the server will appear and any time they do, then the fetch* operations will have been failed. In the other hand nextset will fail (instead of just returning False) when no more result sets are available.
Hope this helps!

pyodbc not committing changes to db2 database

I am trying to update my db2 database using pyodbc in python. The sql statement runs normally without errors on the database directly. when I run the code below, I get no errors and the code executes successfully but when I query the database, the changes did not save.
try:
conn2 = pyodbc.connect("DRIVER={iSeries Access ODBC Driver};SYSTEM="+ Config_Main.iseriesServer +";DATABASE="+ Config_Main.iseriesDB +";UID="+ Config_Main.iseriesUser +";PWD=" + Config_Main.iseriesPass)
db2 = conn2.cursor()
for row in encludeData:
count = len(str(row[2]))
srvid = row[2]
if count < 10:
sql3 = "UPDATE SVCEN2DEV.SRVMAST SET svbrch = ? WHERE svtype != '*DCS-' AND svacct = ? AND svcid LIKE '%?' and svbrch = ?"
db2.execute(sql3, (row[4],row[1],"%" + str(srvid),row[5]))
else:
sql3 = "UPDATE SVCEN2DEV.SRVMAST SET svbrch = ? WHERE svtype != '*DCS-' AND svacct = ? AND svcid = ? and svbrch = ?"
db2.execute(sql3, (row[4],row[1],srvid,row[5]))
conn2.commit()
except pyodbc.Error as e:
logging.error(e)
I have tried setting conn2.autocommit = True. and I have also tried moving the conn2.commit() inside of the for loop to commit after each iteration. I also tried a different driver {IBM i Access ODBC Driver}
EDIT:
Sample of encludeData
['4567890001','4567890001','1234567890','1234567890','foo','bar']
After changing the except statement to grab general errors, the code above now produces this error:
IntegrityError('23000', '[23000] [IBM][System i Access ODBC Driver][DB2 for i5/OS]SQL0803 - Duplicate key value specified. (-803) (SQLExecDirectW)')
As OP found out, the application layer language, Python, may not raise specific database exceptions such as duplicate index or foreign key issues and hence will silently fail or will be logged on server side. Usually errors that affect actual SQL queries to run like incorrect identifiers and syntax errors will raise an error on client side.
Therefore, as best practice in programming it is necessary to use exception handling like Python's try/except/finally or the equivalent in other general purpose languages that interface with any external API like database connections in order to catch and properly handle runtime issues.
Below will print any exception on statements raised in the try block including connection and query execution. And regardless of success or fail will run the finally statements.
try:
conn2 = pyodbc.connect(...)
db2 = conn2.cursor()
sql = "..."
db2.execute(sql, params)
conn2.commit()
except Exception as e:
print(e)
finally:
db2.close()
conn2.close()

Python: Login none error

i'm making a login system for part of my coursework, where it querys the database to see if the data is correct. It works fine until I introduce a login that's not in the database. Is there anyway I can make the while working even after the mycursor.fetchone() gives the error for not fetching anything?
The code below is the subroutine I'm having issues with:
#the error message I'm receiving
username, password = mycursor.fetchone()
TypeError: 'NoneType' object is not iterable
#the subroutine I'm having trouble with
def accept(self):
conn = mysql.connector.connect(user, password, host, database)
#create cursor between python and mysql
mycursor = conn.cursor()
query = """
SELECT
username, password
FROM
UserInfo.User
WHERE
username = %s AND password = %s
"""
mycursor.execute(query, (self.textName.text(),self.textPass.text(), ))
global username
username, password = mycursor.fetchone()
#self.textName.text() and self.textPass.text() is the username and password entered by the user
if username == self.textName.text() and password == self.textPass.text():
self.GoToLogin()
else:
#the error message I want to display
QtGui.QMessageBox.warning(
self, 'Error', 'Username and password are incorrect')
Add try except block and ignore the exception that happens when the record is not found or if multiple records are found.
try:
#db call
except (SpecificException, AnotherException):
pass
It's good to catch specific exceptions than catch all exceptions but in this case you can just catch the global Exception
Also there is no reason to check again if the user and password are equal, since you're already passing that as part of the query.

Categories