MySQLdb in python does not rollback the effect of a trigger - python

In MySQL (version 5.6.32-78.1)
I have 2 tables named Test1, Test2 (say),
where Test1 has a trigger (After INSERT) inserting something into
a 3rd table called Test1A.
I'm using MySQLdb module in python 3.6 to work with my DB.
I'm trying to bundle 2 separate inserts in Test1 and Test2 into a single transaction. The problem I have, is that while the entire transaction might be rolled back due to an error in the 2nd insert, the result of the trigger fired after Insert in Test1 is NOT being rolled back.
So, after the rollback we get back to the states of tables Test1 and Test2 before the transaction, however, the effect of the trigger on Test1 remains.
Any ideas/suggestions ?
Here is the model code
import MySQLdb
cnn = MySQLdb.connect (host = "hostname", user = "username",
passwd = password", db = "dbname")
cursor = cnn.cursor()
try:
cursor.execute( "SET AUTOCOMMIT = 0 " )
print('done with step 1')
s = "Insert INTO Test1 ( field1) Values (%s ) "
cursor.execute(s, ( 'abc', ) ) # this fires a trigger
print('done with step 2')
s = "Insert INTO Test2 (ID, field1) Values (%s, %s)"
cursor.execute( s , ('1', 'aa' ) )
print('done step 3')
cursor.close()
cnn.commit()
print('DONE')
except:
cnn.rollback() # the effect of the trigger on Test1 is not being
print('Rollbacked') # rolled back
The trigger on Test1 is
INSERT INTO
Test1A (field1)
SELECT
Test1.field1 FROM Test1
WHERE
Test1.ID = NEW.ID
A few comments:
If I don't turn off the autocommit, then commit is called on each
insert statement above, so that seems to be necessary.
Of course, one may suggest to put Test1 as the last table inside
a transaction, but that's not an option, as I might need an info from Test1 (say new ID) to operate on Test2.

Already posted this today but anyway here you go :
import pymysql
id = input("Id : ")
name = input("Name : ")
cursor = con.cursor()
cursor.execute(""" INSERT INTO names (id, name) VALUES("%s", "%s")"""
%(id, name))
con.commit()
con.close()
You can see my response on this question :
MySQL db call: not all arguments converted during string formatting
Ask

Related

I run Python 3.10 and MySQL. Commands out of sync; you can't run this command now

import mysql.connector
mydb = mysql.connector.connect(
host = "localhost",
user = "root",
password = "Thsmine2",
database = "_universidad_"
)
cursorrecup = mydb.cursor()
cursorrecup.execute("UPDATE _universidad_.copias SET id_investigadores =8 WHERE id = 10; SELECT * FROM _universidad_.copias")
mydb.commit()
resultadorecup = cursorrecup.fetchall()
for x in resultadorecup:
print(x[0],x[1],x[2],x[3])
I have reduced my problem to these lines, however, there seems to be a problem with the function . I have revised all of my variables and references to the database and they are correct.
You need to iterate over the cursor as it is being executed, rather than over the result. This code works for me:
cur.execute('DROP TABLE IF EXISTS t73955432')
cur.execute('CREATE TABLE t73955432 (a float)')
conn.commit()
cur.executemany('INSERT INTO t73955432 (a) VALUES (%s)', [(1,), (2,), (3,)])
conn.commit()
stmts = 'UPDATE t73955432 set a = RAND(); SELECT a FROM t73955432;'
for result in cur.execute(stmts, multi=True):
print(result.statement)
if result.with_rows:
print(result.fetchall())
else:
print(f'{result.rowcount} rows affected')
conn.commit()
conn.close()
Producing output like
UPDATE t73955432 set a = RAND()
3 rows affected
SELECT a FROM t73955432
[(0.557543,), (0.378451,), (0.21963,)]

Postgres connection in python

I am struggling to establish a connection inside data iteration. Means I am running a select query to postgres and iterating the return data. after some transformation I am writing it to another table. But it is not working. Sample python code is below.
conn = pgconn(------)
cursor = pgconn.Cursor()
query1 = "select * from table"
query2 = "select * from table2 where Id=(%s);"
cursor.execute(query1)
result = query1.fetchall()
for row in result:
If row.a == 2:
cursor.execute(query2, [row.time])
In the above python code I can't able to extract the data by running query2 and passing query1 result as a parameter. It seems cursor is blocked by the query1 so query2 execution is not happening. Please some one help in this issue.
First of all you can write a join statement to do this and can get the data easily
select * from table join table2 where table2.id == table.time
Also why this is not working maybe because the cursor object is getting override inside the for loop and thus the query results get changed.
Use RealDictCursor, and correct the syntax on your inside call to execute():
import psycopg2
import psycopg2.extras
conn = pgconn(------)
cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
query1 = "select * from table"
query2 = "select * from table2 where Id=(%s);"
cursor.execute(query1)
result = query1.fetchall()
for row in result:
If row.a == 2:
cursor.execute(query2, (row['time'],))
1. install psycopg2 and psycopg2.extras. ( pip install)
Then set up your Postgres Connection like:
def Postgres_init(self):
try:
conn = psycopg2.connect(host=os.environ['SD_POSTGRES_SERVER'],
user=os.environ['SD_POSTGRES_USER'],
password=os.environ['SD_POSTGRES_PASSWORD'],
port=os.environ['SD_POSTGRES_PORT'],
database=os.environ['SD_POSTGRES_DATABASE'])
logging.info("Connected to PostgreSQL")
except (Exception, psycopg2.Error) as error:
logging.info(error)
2. Connect your Cursor with the defined connection
cursor = conn.cursor()
3. Execute your query:
cursor.execute("""SELECT COUNT (column1) from tablename WHERE column2 =%s""", (
Value,)) # Check if already exists
result = cursor.fetchone()
Now the value is stored in the "result" variable. Now you can execute the next query like:
cursor.execute("""
INSERT INTO tablename2
(column1, column2, column3)
VALUES
(%s, %s, %s)
ON CONFLICT(column1) DO UPDATE
SET
column2=excluded.column2,
column3=excluded.column3;
""", (result, column2, column3)
)
Now the result of query 1 is stored in the second table in the first column.
Now you can close your connection:
conn.close()

sql (MonetDB) commands from Python stalling

I scripted in Python SQL calls to my MonetDB server (which I verify is running, of course). When I print the calls instead of calling them, the commands look OK, but if I run the original script, it does not crash, it does use the CPU and memory, but nothing is changed in the database, not even the first line is executed. Why?
The Python script looks like this:
# script to merge tables in MonetDB
import re
from monetdb import mapi
server = mapi.Server()
server.connect(hostname="localhost", port=50000, username="monetdb", password="monetdb", database="dbfarm", language="sql")
def tablemerge(stub,yearlist):
for year in yearlist:
# server.cmd('ALTER TABLE %s_%d ADD COLUMN "year" INTEGER DEFAULT %d;' % (stub,year,year))
print 'ALTER TABLE %s_%d ADD COLUMN "year" INTEGER DEFAULT %d;' % (stub,year,year)
newstub = re.sub(r'sys.ds_chocker_lev_', r'', stub)
if year == yearlist[0]:
unioncall = 'CREATE TABLE %s AS SELECT * FROM %s_%d ' % (newstub,stub,year)
else:
unioncall += 'UNION ALL SELECT * FROM %s_%d ' % (stub,year)
unioncall += ';'
server.cmd(unioncall)
# print unioncall
for year in yearlist:
server.cmd('DROP TABLE %s_%d;' % (stub,year))
# print 'DROP TABLE %s_%d;' % (stub,year)
print '%s done.' % stub
for stub in ['civandr']:
tablemerge('sys.ds_chocker_lev_%s' % stub,xrange(1998,2013))
E.g. the first call would be:
ALTER TABLE sys.ds_chocker_lev_civandr_1998 ADD COLUMN "year" INTEGER DEFAULT 1998;
But not even this happens. There is no year column in the table.
Or could I run the script in the console with more output than what I print myself?
Do commit! By default, the autocommit parameter is set to False. You can either do:
server.connect(hostname="localhost", port=50000, username="monetdb", password="monetdb", database="dbfarm", language="sql", autocommit=True)
or simply run:
connection.commit()
connection = monetdb.sql.connect(username=username,password=password,hostname=hostname,port=port,database=database)
cursor = connection.cursor()
cursor.execute('create table test (id int, name varchar(50));')
connection.commit()

sqlite3.Warning: You can only execute one statement at a time

I get the error when running this code:
import sqlite3
user_name = raw_input("Please enter the name: ")
user_email = raw_input("Please enter the email: ")
db = sqlite3.connect("customer")
cursor=db.cursor()
sql = """INSERT INTO customer
(name, email) VALUES (?,?);,
(user_name, user_email)"""
cursor.execute(sql)
Why is this happening?
While the other posters are correct about your statement formatting you are receiving this particular error because you are attempting to perform multiple statements in one query (notice the ; in your query which separates statements).
From Python sqlite3 docs:
"execute() will only execute a single SQL statement. If you try to execute more than one
statement with it, it will raise a Warning. Use executescript() if you want to execute
multiple SQL statements with one call."
https://docs.python.org/2/library/sqlite3.html
Now your statement will not execute properly even if you use executescript() because there are other issues with the way it is formatted (see other posted answers). But the error you are receiving is specifically because of your multiple statements. I am posting this answer for others that may have wandered here after searching for that error.
Use executescript instead of execute
execute() will only execute a single SQL statement. If you try to execute more than one statement with it, it will raise a Warning. Use executescript() if you want to execute multiple SQL statements with one call.
https://docs.python.org/2/library/sqlite3.html#sqlite3.Cursor.execute
You have a ;, in the middle of the query string - that is an invalid syntax. Pass a dictionary as a second argument to execute if you want to use a named parameter binding.
sql = "INSERT INTO customer (name, email) VALUES (:name, :email)"
cursor.execute(sql, {'name':user_name, 'email':user_email})
Try this:
sql = """INSERT INTO customer
(name, email) VALUES (?,?)"""
cursor.execute(sql, (user_name, user_email))
import sqlite3
def DB():
List = {"Name":"Omar", "Age":"33"}
columns = ', '.join("" + str(x).replace('/', '_') + "" for x in List.keys())
values = ', '.join("'" + str(x).replace('/', '_') + "'" for x in List.values())
sql_qry = "INSERT INTO %s ( %s ) values (?,?) ; ( %s )" % ('Table Name', columns, values)
conn = sqlite3.connect("DBname.db")
curr = conn.cursor()
# curr.execute("""create table if not exists TestTable(
# Name text,
# Age text
# )""")
# print columns
# print values
# print sql
# sql = 'INSERT INTO yell (Name , Age) values (%s, %s)'
curr.execute(sql_qry)
DB()

TypeError: 'NoneType' object is not iterable

I need to process mysql data one row at a time and i have selected all rows put them in a tuple but i get the error above.
what does this mean and how do I go about it?
Provide some code.
You probably call some function that should update database, but the function does not return any data (like cursor.execute()). And code:
data = cursor.execute()
Makes data a None object (of NoneType). But without code it's hard to point you to the exact cause of your error.
It means that the object you are trying to iterate is actually None; maybe the query produced no results?
Could you please post a code sample?
The function you used to select all rows returned None. This "probably" (because you did not provide code, I am only assuming) means that the SQL query did not return any values.
Try using the cursor.rowcount variable after you call cursor.execute(). (this code will not work because I don't know what module you are using).
db = mysqlmodule.connect("a connection string")
curs = dbo.cursor()
curs.execute("select top 10 * from tablename where fieldA > 100")
for i in range(curs.rowcount):
row = curs.fetchone()
print row
Alternatively, you can do this (if you know you want ever result returned):
db = mysqlmodule.connect("a connection string")
curs = dbo.cursor()
curs.execute("select top 10 * from tablename where fieldA > 100")
results = curs.fetchall()
if results:
for r in results:
print r
This error means that you are attempting to loop over a None object. This is like trying to loop over a Null array in C/C++. As Abgan, orsogufo, Dan mentioned, this is probably because the query did not return anything. I suggest that you check your query/databse connection.
A simple code fragment to reproduce this error is:
x = None
for each i in x:
#Do Something
pass
This may occur when I try to let 'usrsor.fetchone' execute twice. Like this:
import sqlite3
db_filename = 'test.db'
with sqlite3.connect(db_filename) as conn:
cursor = conn.cursor()
cursor.execute("""
insert into test_table (id, username, password)
values ('user_id', 'myname', 'passwd')
""")
cursor.execute("""
select username, password from test_table where id = 'user_id'
""")
if cursor.fetchone() is not None:
username, password = cursor.fetchone()
print username, password
I don't know much about the reason. But I modified it with try and except, like this:
import sqlite3
db_filename = 'test.db'
with sqlite3.connect(db_filename) as conn:
cursor = conn.cursor()
cursor.execute("""
insert into test_table (id, username, password)
values ('user_id', 'myname', 'passwd')
""")
cursor.execute("""
select username, password from test_table where id = 'user_id'
""")
try:
username, password = cursor.fetchone()
print username, password
except:
pass
I guess the cursor.fetchone() can't execute twice, because the cursor will be None when execute it first time.
I know it's an old question but I thought I'd add one more possibility. I was getting this error when calling a stored procedure, and adding SET NOCOUNT ON at the top of the stored procedure solved it. The issue is that earlier selects that are not the final select for the procedure make it look like you've got empty row sets.
Try to append you query result to a list, and than you can access it. Something like this:
try:
cursor = con.cursor()
getDataQuery = 'SELECT * FROM everything'
cursor.execute(getDataQuery)
result = cursor.fetchall()
except Exception as e:
print "There was an error while getting the values: %s" % e
raise
resultList = []
for r in result:
resultList.append(r)
Now you have a list that is iterable.

Categories

Resources