I'm having a problem where I have a SQL statement that when run in my MySQL Workbench executes properly, but when run with python's mysql package function cursor.execute() doesn't work. The problem SQL statement is:
REPLACE INTO mmm_dev.samp_wp_links SELECT * FROM mmm_master.samp_wp_links;
The statement is supposed to copy all data from mmm_master into mmm_dev. The following the python code that I'm using to execute the query:
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
def examine(cursor, cnx):
try:
qry = cursor.execute("REPLACE INTO mmm_dev.samp_wp_links SELECT * FROM mmm_master.samp_wp_links;")
except mysql.connector.Error as err:
print("Failed to select everything")
exit(1)
MySQL Python libraries are PEP 249-compliant:
.commit () Commit any pending transaction to the database.
Note that if the database supports an auto-commit feature, this must
be initially off. An interface method may be provided to turn it back
on.
Database modules that do not support transactions should implement
this method with void functionality.
Call cnx.commit()
Call examine(). Debug with print():
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
def examine(cursor):
print("[DEBUG] 1: before query")
try:
qry = cursor.execute("REPLACE INTO mmm_dev.samp_wp_links SELECT * FROM mmm_master.samp_wp_links;")
print("[DEBUG] 2: after query")
except mysql.connector.Error as err:
print("Failed to select everything %s" % err)
exit(1)
print("[DEBUG] 3: success")
examine(cursor)
You have to do a commit.
mydb.commit()
in order to save the changes.
Related
I am writing a python script that does the following as a part a transaction.
Creates a new database.
Creates new tables using a schema.sql file.
Copies the data from the master DB to this new DB using insert into select * from master.table_name... like SQL statements.
Commits the txn, in the else block, if everything goes right. Rollback the txn, in the except block, if something goes wrong.
Close the connection in the finally block.
However, while testing, I found out that rollback isn't working. If an exception is raised after DB is created, even after rollback, DB is created. If an exception is raised after inserting data into a few tables with some tables remaining, calling rollback in the except block does not revert the inserted data. The script looks like this:
import mysql.connector
try:
conn = mysql.connector.connect(host='localhost', port=3306,
user=USERNAME, password=PASSWORD,
autocommit=False)
cursor.execute("START TRANSACTION;")
cursor.execute(f"DROP DATABASE IF EXISTS {target_db_name};")
cursor.execute(f"CREATE DATABASE {target_db_name};")
cursor.execute(f"USE {target_db_name};")
with open(SCHEMA_LOCATION) as f:
schema_query = f.read()
commands = schema_query.split(";")
for command in commands:
cursor.execute(command)
for query in QUERIES:
cursor.execute(f"{query}{org_Id};")
except Exception as error:
conn.rollback()
else:
conn.commit() # cursor.execute("COMMIT")
finally:
if conn.is_connected():
cursor.close()
conn.close()
Below are the details of the setup
Python3
mysql-connector-python==8.0.32
MySQL 5.7
Storage Engine: InnoDB
I am attempting to INSERT INTO using a correct SQL query and Python's PyMySQL package. I know it is correct since the same query, when doing a Copy/Paste into mySQL workbench, inserts it all right!
However, using Python's pymysql package and cursor.executemany() it fails silently, and returns as rowcount minus 1 (-1).
Here is the piece of code:
ins_query = "REPLACE INTO `household`.`expenses`(`ID`,`Date`,`Sum`,`Class`,`Description`,`Necessity`) VALUES (NULL,'2021-12-23', 800, 'Groceries','Test-3',NULL )"
# ------------------------------
cursor = self.conn.cursor()
try:
cursor.executemany(ins_query)
except pymysql.Error as e:
print("Error %d: %s" % (e.args[0], e.args[1]))
return False
self.conn.commit()
return cursor.rowcount
I'm still using Flask-mysql.
I'm getting the database context (the mysql variable) just fine, and can query on the database / get results. It's only the insert that is not working: it's not complaining (throwing Exceptions). It returns True from the insert method.
This should be done inserting the record when it commits, but for some reason, as I watch the MySQL database with MySQL Workbench, nothing is getting inserted into the table (and it's not throwing exceptions from the insert method):
I'm passing in this to insertCmd:
"INSERT into user(username, password) VALUES ('test1','somepassword');"
I've checked the length of the column in the database, and copied the command into MySQL Workbench (where it successfully inserts the row into the table).
I'm at a loss. The examples I've seen all seem to follow this format, and I have a good database context. You can see other things I've tried in the comments.
def insert(mysql, insertCmd):
try:
#connection = mysql.get_db()
cursor = mysql.connect().cursor()
cursor.execute(insertCmd)
mysql.connect().commit()
#mysql.connect().commit
#connection.commit()
return True
except Exception as e:
print("Problem inserting into db: " + str(e))
return False
You need to keep a handle to the connection; you keep overriding it in your loop.
Here is a simplified example:
con = mysql.connect()
cursor = con.cursor()
def insert(mysql, insertCmd):
try:
cursor.execute(insertCmd)
con.commit()
return True
except Exception as e:
print("Problem inserting into db: " + str(e))
return False
If mysql is your connection, then you can just commit on that, directly:
def insert(mysql, insertCmd):
try:
cursor = mysql.cursor()
cursor.execute(insertCmd)
mysql.commit()
return True
except Exception as e:
print("Problem inserting into db: " + str(e))
return False
return False
Apparently, you MUST separate the connect and cursor, or it won't work.
To get the cursor, this will work: cursor = mysql.connect().cursor()
However, as Burchan Khalid so adeptly pointed out, any attempt after that to make a connection object in order to commit will wipe out the work you did using the cursor.
So, you have to do the following (no shortcuts):
connection = mysql.connect()
cursor = connection.cursor()
cursor.execute(insertCmd)
connection.commit()
I've got psycopg2 running and I can successfully query tables of my database. This is a working example of querying the table my_table:
import psycopg2
try:
conn_string="dbname='my_dbname' user='user' host='localhost' password='password'"
print "Connecting to database\n->%s" % (conn_string)
conn = psycopg2.connect(conn_string)
print "connection succeeded"
except:
print "no connection to db"
cur = conn.cursor()
try:
cur.execute(""" SELECT * from my_table; """)
records = cur.fetchall()
cur.close()
except:
print "Query not possible"
Question: How can I query a view, let it be called my_view, within the same database my_dbname?
The same way you'd query a table. From a SELECT point of view, a VIEW is the exact same thing as a TABLE:
cur.execute("SELECT * from my_view")
Note that you generally do not want to use a black except:. Catch a specific exception if you have to, but you are usually better off not catching the exception at all rather than block all feedback on errors as you've done here.
I have installed python 2.7 64bit,MySQL-python-1.2.3.win-amd64-py2.7.exe.
I use the following code to insert data :
class postcon:
def POST(self):
conn=MySQLdb.connect(host="localhost",user="root",passwd="mysql",db="dang",charset="utf8")
cursor = conn.cursor()
n = cursor.execute("insert into d_message (mid,title,content,image) values(2,'xx','ccc','fff')")
cursor.close()
conn.close()
if n:
raise web.seeother('/')
This results in printing n as 1, but in mysql client data aren't visible.
google says I must add conn.autocommit(True).
but I don't know why MySQLdb turns it off;
by default MySQLdb autocommit is false,
You can set autocommit to True in your MySQLdb connection like this,
conn=MySQLdb.connect(host="localhost",user="root",passwd="mysql",db="dang",charset="utf8")
conn.get_autocommit() #will return **False**
conn.autocommit(True)
conn.get_autocommit() #Should return **True** now
cursor = conn.cursor()
I don't know if there's a specific reason to use autocommit with GAE (assuming you are using it). Otherwise, you can just manually commit.
class postcon:
def POST(self):
conn=MySQLdb.connect(host="localhost",user="root",passwd="mysql",db="dang",charset="utf8")
cursor = conn.cursor()
n = cursor.execute("insert into d_message (mid,title,content,image) values(2,'xx','ccc','fff')")
conn.commit() # This right here
cursor.close()
conn.close()
if n:
raise web.seeother('/')
Note that you probably should check if the insert happened successfully, and if not, rollback the commit.
Connector/Python Connection Arguments
Turning on autocommit can be done directly when you connect to a database:
import mysql.connector as db
conn = db.connect(host="localhost", user="root", passwd="pass", db="dbname", autocommit=True)
or
import mysql.connector
db = mysql.connector.connect(option_files='my.conf', autocommit=True)
Or call conn.commit() before calling close.