PostgreSQL INSERT ON CONFLICT and TKinter - python

I have problem with syntax within python/Tkinter when updating PostgreSQL table.
Syntax works for function code below without ON CONFLICT option:
def myclick_start():
# Create a database or connect to one
conn = psycopg2.connect(database="*",# hidden credentials here
host="*",
user="*",
password="*",
port="*")
# Create cursor
c = conn.cursor()
# Insert Into Database Table
thing1 = o_num.get()
thing2 = op_id.get()
thing3 = proc_name_cb.get()
# this works
c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)''',
(thing1, thing2, thing3)
)
# Commit Changes
conn.commit()
# Close Connection
conn.close()
but not working when I want to UPDATE table ON CONFLICT of order_id value:
# but this is not working
c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)''',
(thing1, thing2, thing3),
ON CONFLICT (order_id)
DO UPDATE SET op_id = EXCLUDED.op_id, status_id = EXCLUDED.status_id;
)
Resulted error:
File "E:\***.py", line 229
'''c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)''',
^^^^^^
SyntaxError: invalid syntax
I've tried many syntax variants and kind of stuck with my error.
Appreciate your help.

If you take a closer look at the syntax highlight, you will notice that your ON CONFLICT ... isn't part of the SQL query (i.e. it's not part of the string that makes up the query).
Moving that part inside the string should solve the problem, like this
c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)
ON CONFLICT (order_id)
DO UPDATE SET op_id = EXCLUDED.op_id, status_id = EXCLUDED.status_id;''',
(thing1, thing2, thing3)
)

Related

Problem to insert with psycopg2 with python

I'm trying to insert some rows, but this problema occurs:
TypeError: not all arguments converted during string formatting
sql code:
f"""insert into {table} ({insert}) VALUES ({formating}) ON CONFLICT ({', '.join(key)}) DO UPDATE SET ({insert}) = ({excluded})"""
sql translate:
insert into public.atend (cd_atendimento, cd_ori_ate, cd_paciente, op_type) VALUES (%s, %s, %s, %s) ON CONFLICT (cd_atendimento) DO UPDATE SET (cd_atendimento, cd_ori_ate, cd_paciente, op_type) = (EXCLUDED.cd_atendimento, EXCLUDED.cd_ori_ate, EXCLUDED.cd_paciente, EXCLUDED.op_type)

Executing multiple SQL queries with Python Flask

I have a python function which should execute 2 SQL queries. I have found that it is impossible to execute 2 queries in one command at once, so as a workaround I created a list of my queries and try to iterate over it with execute command. However nothing is added to MySQL table. Here is the code:
#app.route('/addComment', methods=['POST'])
def addComment():
try:
if session.get('user'):
_description = request.form['description']
_user = session.get('user')
_term_id = request.form['termID']
_time = datetime.now()
operation = ['"INSERT INTO comments (description, user, termID, time) VALUES (%s, %s, %s, %s)", (_description, _user, _term_id, _time)', '"INSERT INTO history (user, term, time) VALUES (%s, %s, %s)", (_user, _term_id, _time)']
conn = mysql.connect()
cursor = conn.cursor()
for item in operation:
cursor.execute()
conn.commit()
data = cursor.fetchall()
if len(data) == 0:
conn.commit()
return json.dumps({'status':'OK'})
else:
return json.dumps({'status':'ERROR'})
except Exception as e:
return json.dumps({'status':'Unauthorized access'})
finally:
cursor.close()
conn.close()
Could you please help me?
Errors in your code lies in the following areas:
A. On iteration sql statement is not passed to execute()
Should be:
for item in operation:
cursor.execute(item)
conn.commit()
B. Invalid parameterization
'"INSERT INTO comments (description, user, termID, time) VALUES (%s, %s, %s, %s)", (_description, _user, _term_id, _time)'
This string statement doesn't apply variables to SQL statement string. Depending on your value types you should decide whether to add ' (apostrophe) or not. More safely would be to pass parameters to .execute() function. Example below.
cursor.execute(
"INSERT INTO comments (description, user, termID, time) VALUES (:description, :user, :term_id, :time)",
description=_description,
user=_user,
term_id=_term_id,
time=_time
)

Anyway to Upsert database using PostgreSQL in Python

I want to upsert with least effort, for simplicity, i reduce columns, this not work:
sql = '''INSERT INTO temp.tickets
(id, created_at, updated_at, emails, status)
VALUES
(%s, %s, %s, %s, %s)
ON CONFLICT (id)
DO UPDATE SET ( emails, status) values (%s,%s)
'''
cursor = cm.cursor()
## cm is a custom module
cursor.execute(sql, (ticket['id'],
ticket['created_at'],
ticket['updated_at'],
ticket['emails'], ticket['status'], )
This code show Error:
return super(DictCursor, self).execute(query, vars)
IndexError: tuple index out of range
What I need to change in the cursor.execute() to work?
The Bellow code work but I like to use %s instead of type: email = excluded.email for each columns
sql = '''INSERT INTO temp.tickets
(id, created_at, updated_at, emails, status)
VALUES
(%s, %s, %s, %s, %s)
ON CONFLICT (id)
DO UPDATE SET emails = excluded.eamils, status = excluded.status
'''
cursor = cm.cursor()
# cm is a custom module
cursor.execute(sql, (ticket['id'],
ticket['created_at'],
ticket['updated_at'],
ticket['emails'], ticket['status'], )
There are two Relevant Questions link1, link2
I would try something like this:
sql = '''INSERT INTO temp.tickets
(id, created_at, updated_at, emails, status)
VALUES
(%s, %s, %s, %s, %s)
ON CONFLICT (id)
DO UPDATE SET ( emails, status) values (%s,%s)
'''
cursor = cm.cursor()
## cm is a custom module
cursor.execute(sql, (ticket['id'],
ticket['created_at'],
ticket['updated_at'],
ticket['emails'],
ticket['status'],
ticket['emails'],
ticket['status'] )
Thre number of %s must match the number of parameters.
When Postgres encounters a captured conflict it basically creates a record called EXCLUDED that contains the values you attempted to insert, You can refer to this record in DO UPDATE. Try the following:
INSERT INTO temp.tickets
(id, created_at, updated_at, emails, status)
VALUES
(%s, %s, %s, %s, %s)
ON CONFLICT (id)
DO UPDATE
SET emails = excluded.emails
, status = excluded.status
, updated_at = excluded.updated_at -- my assumption.
...
You will have to format is into the requirements of your source language.

MySQL not accepting executemany() INSERT, running Python from Excel (datanitro)

I HAVE ADDED MY OWN ANSWER THAT WORKS BUT OPEN TO IMPROVEMENTS
After seeing a project at datanitro. I took on getting a connection to MySQL (they use SQLite) and I was able to import a small test table into Excel from MySQL.
Inserting new updated data from the Excel sheet was this next task and so far I can get one row to work like so...
import MySQLdb
db = MySQLdb.connect("xxx","xxx","xxx","xxx")
c = db.cursor()
c.execute("""INSERT INTO users (id, username, password, userid, fname, lname)
VALUES (%s, %s, %s, %s, %s, %s);""",
(Cell(5,1).value,Cell(5,2).value,Cell(5,3).value,Cell(5,4).value,Cell(5,5).value,Cell(5,6).value,))
db.commit()
db.close()
...but attempts at multiple rows will fail. I suspect either issues while traversing rows in Excel. Here is what I have so far...
import MySQLdb
db = MySQLdb.connect(host="xxx.com", user="xxx", passwd="xxx", db="xxx")
c = db.cursor()
c.execute("select * from users")
usersss = c.fetchall()
updates = []
row = 2 # starting row
while True:
data = tuple(CellRange((row,1),(row,6)).value)
if data[0]:
if data not in usersss: # new record
updates.append(data)
row += 1
else: # end of table
break
c.executemany("""INSERT INTO users (id, username, password, userid, fname, lname) VALUES (%s, %s, %s, %s, %s, %s)""", updates)
db.commit()
db.close()
...as of now, I don't get any errors, but my new line is not added (id 3). This is what my table looks like in Excel...
The database holds the same structure, minus id 3. There has to be a simpler way to traverse the rows and pull the unique content for INSERT, but after 6 hours trying different things (and 2 new Python books) I am going to ask for help.
If I run either...
print '[%s]' % ', '.join(map(str, updates))
or
print updates
my result is
[]
So this is likely not passing any data to MySQL in the first place.
LATEST UPDATE AND WORKING SCRIPT
Not exactly what I want, but this has worked for me...
c = db.cursor()
row = 2
while Cell(row,1).value != None:
c.execute("""INSERT IGNORE INTO users (id, username, password, userid, fname, lname)
VALUES (%s, %s, %s, %s, %s, %s);""",
(CellRange((row,1),(row,6)).value))
row = row + 1
Here is your problem:
while True:
if data[0]:
...
else:
break
Your first id is 0, so in the first iteration of the loop data[0] will be falsely and your loop will exit, without ever adding any data. What you probably ment is:
while True:
if data[0] is not None:
...
else:
break
I ended up finding a solution that gets me an Insert on new and allows for UPDATE of those that are changed. Not exactly a Python selection based on a single query, but will do.
import MySQLdb
db = MySQLdb.connect("xxx","xxx","xxx","xxx")
c = db.cursor()
row = 2
while Cell(row,1).value is not None:
c.execute("INSERT INTO users (id, username, password, \
userid, fname, lname) \
VALUES (%s, %s, %s, %s, %s, %s) \
ON DUPLICATE KEY UPDATE \
id=VALUES(id), username=VALUES(username), password=VALUES(password), \
userid=VALUES(userid), fname=VALUES(fname), lname=VALUES(lname);",
(CellRange((row,1),(row,6)).value))
row = row + 1
db.commit()
db.close()

getting error with execute many in python

I am learning python and i am new bie.
I am trying to use functions with mysql and python and i ma getting errors
This is my script
import MySQLdb
def insert_values(cursor, values):
#cursor = self.connection.cursor()
cursor.executemany("""
insert into pythontest (name1,name2,name3)
values (%s, %s, %s)""", values)
cursor.close()
db = MySQLdb.connect("localhost","root","root","python" )
cursor = db.cursor()
var1 = ['name1','name2','name3']
insert_values(cursor,var1)
db.close()
There may be many errors because i am learning
1)i don't know how can i pass db
object in function or passing cusrsor
is ok. because i have to call that
function many times in for loop
2)is the syntax of values array ok to
go in database
ERRORS
File "mysql.py", line 10, in insert_values
values (%s, %s, %s)""", values)
File "build/bdist.linux-i686/egg/MySQLdb/cursors.py", line 216, in executemany
File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 36, in defaulterrorhandler
_mysql_exceptions.ProgrammingError: not enough arguments for format string
cursor.executemany("""
insert into pythontest (name1,name2,name3)
values (%s, %s, %s)""", *values)
Here's how I would write that (But untested):
import MySQLdb
def insert_values(db, values):
cursor = db.cursor()
try:
try:
cursor.execute("""
insert into pythontest (name1,name2,name3)
values (%s, %s, %s)""", *values)
except:
db.rollback()
raise
else:
db.commit()
finally:
cursor.close()
db = MySQLdb.connect("localhost","root","root","python" )
vars = ('name1','name2','name3')
insert_values(db, vars)
db.close()
The cursor starts a transaction, so you don't want to re-use the same cursor for multiple updates unless they are part of an atomic transaction.

Categories