sqlalchemy, insert with try except block - python

I have a query that I intend to insert with a try-except block, so that I can ignore all the queries that fail a certain constraint i.e. IntegrityError.
with sql_engine.begin() as cn:
sql = """INSERT INTO table1 (m_id, pick_on)
SELECT t.m_id, t.pick_on
FROM temp_table t
WHERE NOT EXISTS
(SELECT 1 FROM table1 f
WHERE (t.m_id = f.m_id
OR (t.m_id IS NULL AND f.m_id IS NULL))
AND t.pick_on = f.pick_on)"""
try:
cn.execute(sql)
except:
print("Unexpected error:", sys.exc_info()[0])
print(sql)
pass
but this does not insert all the records to table1. why?

Related

How to call a Python function from a SQLite trigger

This is my trigger
cursor.execute(
'''CREATE TRIGGER IF NOT EXISTS Car_Park_row_
BEFORE INSERT ON Car_Park
WHEN (SELECT COUNT(*) FROM Car_PARK) >= 10
BEGIN
SELECT RAISE (ABORT, 'FULL');
END;
and this is my function
def C(x):
print('Error')
# Create Database
connector = sqlite3.connect('cparks.db')
connector.create_function("sql", -1, C)
cursor = connector.cursor()
I've limited my rows on my database to 10 with the trigger. What I need now is a message box or something along the lines of to appear to let the GUI user know that the table is full.
Executing the RAISE() function in a query raises a sqlite3.IntegrityError exception in the Python code which you can handle like any other exception.
Example script:
import sqlite3
db = sqlite3.connect(':memory:')
db.executescript('''
CREATE TABLE car_park (car);
CREATE TRIGGER car_park_row
BEFORE INSERT ON car_park
WHEN (SELECT count(*) FROM car_park) >= 10
BEGIN
SELECT RAISE (ABORT, 'full');
END;
''')
for i in range(15):
car = f'car{i}'
try:
res = db.execute('insert into car_park values (?)', (car,))
except sqlite3.IntegrityError as e:
print(f'Could not insert {car}: {e}')
for row in db.execute('SELECT * FROM car_park'):
print(row)
Output:
Could not insert car10: full
Could not insert car11: full
Could not insert car12: full
Could not insert car13: full
Could not insert car14: full
('car0',)
('car1',)
('car2',)
('car3',)
('car4',)
('car5',)
('car6',)
('car7',)
('car8',)
('car9',)
(It may be advisable to break out of the loop if an error occurs, it is not done here just for demonstration purposes.)
Instead of printing an error message, you can call any Python function in the exception handler. You do not need to add a user-defined function to the database to do this:
def handle_insert_car_error(car, error):
create_message_box(f'Could not insert {car}: {error}') # or whatever
Then:
# ...
try:
res = db.execute('insert into car_park values (?)', (car,))
except sqlite3.IntegrityError as e:
handle_insert_car_error(car, e)

How to continue loop and log error when validation error is raised in exception?

I'm pretty new to python but I have created a small script to insert rows in postgres, and a table that stores stock prices.
The table have a unique constraint on date and ticker, to ensure only one price per ticker per day is inserted. I want the script to skip inserts and continue on with the rest, but I cannot figure out how to make the loop continue when the exception block is triggered.
The Python script is as follows:
def createConnection(db="db", user="john", password='doe', host='host', port=5432):
conn = psycopg2.connect(
database=db, user=user, password=password, host=host, port=port)
return conn
def insertNewPrices(df):
conn = createConnection()
cur = conn.cursor()
for row in df.head().itertuples(index=False):
try:
print(row)
cur.execute(
"INSERT INTO daily_price (price_date, ticker, close_price) VALUES (%s, %s,
%s)", row)
except psycopg2.IntegrityError as e:
print("something went wrong")
print(e)
continue
conn.commit()
conn.close()
error raised:
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "daily_price_ticker_price_date_key"
DETAIL: Key (ticker, price_date)=(EQUINOR, 1990-02-28) already exists.
You have the insert statement outside the try statement. Can you remove the insert from outside and you should be OK.
for row in df.head().itertuples(index=False):
#cur.execute(
# "INSERT INTO daily_price (price_date, ticker, close_price) VALUES (%s, %s, %s)",
row)
try:
print(row)
cur.execute(
"INSERT INTO daily_price (price_date, ticker, close_price) VALUES (%s, %s,
%s)", row)
except psycopg2.IntegrityError, psycopg2.errors.UniqueViolation) as e:
print("something went wrong")
print(e)
Also you don't need continue at the end of the except statement as its the last line.
Instead of checking for specific errors, you can also catch all errors and warnings using the below:
except (psycopg2.Error, psycopg2.Warning) as e:

Python "INSERT INTO" vs. "INSERT INTO...ON DUPLICATE KEY UPDATE"

I am trying to use python to insert a record into a MySQL database and then update that record. To do this I have created 2 functions:
def insert_into_database():
query = "INSERT INTO pcf_dev_D.users(user_guid,username) VALUES (%s, %s) "
data = [('1234', 'user1234')]
parser = ConfigParser()
parser.read('db/db_config.ini')
db = {}
section = 'mysql'
if parser.has_section(section):
items = parser.items(section)
for item in items:
db[item[0]] = item[1]
else:
raise Exception('{0} not found in the {1} file'.format(section, filename))
try:
conn = MySQLConnection(**db)
cursor = conn.cursor()
cursor.executemany(query, data)
conn.commit()
except Error as e:
print('Error:', e)
finally:
# print("done...")
cursor.close()
conn.close()
This works fine and inserts 1234, user1234 into the db.
Now I want to update this particular user's username to '5678', so I have created another function:
def upsert_into_database():
query = "INSERT INTO pcf_dev_D.users(user_guid,username) " \
"VALUES (%s, %s) ON DUPLICATE KEY UPDATE username='%s'"
data = [('1234', 'user1234', 'user5678')]
parser = ConfigParser()
parser.read('db/db_config.ini')
db = {}
section = 'mysql'
if parser.has_section(section):
items = parser.items(section)
for item in items:
db[item[0]] = item[1]
else:
raise Exception('{0} not found in the {1} file'.format(section, 'db/db_config.ini'))
try:
conn = MySQLConnection(**db)
cursor = conn.cursor()
cursor.executemany(query, data)
conn.commit()
except Error as e:
print('Error:', e)
finally:
# print("done...")
cursor.close()
conn.close()
Which produces the following error:
Error: Not all parameters were used in the SQL statement
What's interesting is if I modify query and data to be:
query = "INSERT INTO pcf_dev_D.users(user_guid,username) " \
"VALUES (%s, %s) ON DUPLICATE KEY UPDATE username='user5678'"
data = [('1234', 'user1234')]
Then python updates the record just fine...what am I missing?
You included the 3rd parameter within single quotes in the update clause, therefore it is interpreted as part of a string, not as a placeholder for parameter. You must not enclose a parameter by quotes:
query = "INSERT INTO pcf_dev_D.users(user_guid,username) " \
"VALUES (%s, %s) ON DUPLICATE KEY UPDATE username=%s"
UPDATE
If you want to use the on duplicate key update clause with a bulk insert (e.g. executemany()), then you should not provide any parameters in the update clause because you can only have one update clause in the bulk insert statement. Use the values() function instead:
query = "INSERT INTO pcf_dev_D.users(user_guid,username) " \
"VALUES (%s, %s) ON DUPLICATE KEY UPDATE username=VALUES(username)"
In assignment value expressions in the ON DUPLICATE KEY UPDATE clause, you can use the VALUES(col_name) function to refer to column values from the INSERT portion of the INSERT ... ON DUPLICATE KEY UPDATE statement. In other words, VALUES(col_name) in the ON DUPLICATE KEY UPDATE clause refers to the value of col_name that would be inserted, had no duplicate-key conflict occurred. This function is especially useful in multiple-row inserts. The VALUES() function is meaningful only in the ON DUPLICATE KEY UPDATE clause or INSERT statements and returns NULL otherwise.

sqlite3 failing to create/insert table

Im doing:
try:
conn = sqlite3.connect('bags_of_coins.db')
print('Db Creation Successful')
except:
print('Db Creation NOT Successful')
try:
conn.execute('''CREATE TABLE bags
(ID INTEGER PRIMARY KEY,
bag TEXT NOT NULL,
);''')
print('Table Creation Successful')
except:
print('Table Creation NOT Successful')
try:
conn.execute("INSERT INTO bags (bag) \
VALUES ('test')");
conn.commit()
except:
print('Insert NOT Successful')
#finally.
conn.close()
But it keeps outputting:
Db Creation Successful
Table Creation NOT Successful
Insert NOT Successful
Does anyone see anything i'm doing wrong? I was following this guide but I cant see to spot the issue. Thanks.
You have comma before ) in this place:
CREATE TABLE bags
(ID INTEGER PRIMARY KEY,
bag TEXT NOT NULL, <- here
);
delete it.
Try this:
import sqlite3
conn = None
try:
conn = sqlite3.connect('bags_of_coins.db')
print('Db Creation Successful')
except:
print('Db Creation NOT Successful')
try:
with conn:
conn.execute("CREATE TABLE bags (ID INTEGER PRIMARY KEY, bag TEXT NOT NULL);")
print('Table Creation Successful')
cursor = conn.execute("INSERT INTO bags (bag) VALUES ('test')")
conn.commit()
print("Insert Successful" if cursor.rowcount > 0 else "Insert NOT Successful")
except:
print('Table Creation NOT Successful')
Your error was creating the table.
The 'with' is a plus I added, it takes care of closing the connection when the block finish by any reason so you don't need the 'finally' block.
Don't hesitate to ask if you have any doubt.
Blindly banging out try..except without showing the error from the exception is just going to cause you grief and heartache, use the exception available to list the specific error.
import sqlite3
try:
conn = sqlite3.connect('bags_of_coins.db')
except sqlite3.Error as e:
print('Db Creation NOT Successful', str(e))
mycursor = conn.cursor()
try:
mycursor.execute("CREATE TABLE bags (ID INTEGER PRIMARY KEY,bag TEXT NOT NULL)")
except sqlite3.Error as e:
print("Table creation failed", str(e))
try:
mycursor.execute("insert into bags (bag) values (?)", (['test']))
conn.commit()
except sqlite3.Error as e:
print("table insert failed", str(e))
#finally.
conn.close()

Postgresql Python: ignore duplicate key exception

I insert items using psycopg2 in the following way:
cursor = connection.cursor()
for item in items:
try:
cursor.execute(
"INSERT INTO items (name, description) VALUES (%s, %s) RETURNING id",
(item[0], item[1])
)
id = cursor.fetchone[0]
if id is not None:
cursor.execute(
"INSERT INTO item_tags (item, tag) VALUES (%s, %s) RETURNING id",
(id, 'some_tag')
)
except psycopg2.Error:
connection.rollback()
print("PostgreSQL Error: " + e.diag.message_primary)
continue
print(item[0])
connection.commit()
Obviously, when an item is already in the database, the duplicate key exception is being thrown. Is there a way to ignore the exception? Is the whole transaction is going to be aborted when the exception is thrown? If yes, then what is the best option to rewrite the query, maybe using batch inserting?
from Graceful Primary Key Error handling in Python/psycopg2:
You should rollback transaction on error.
I've added one more try..except..else construction in the code bellow
to show the exact place where exception will occur.
try:
cur = conn.cursor()
try:
cur.execute( """INSERT INTO items (name, description)
VALUES (%s, %s) RETURNING id""", (item[0], item[1]))
except psycopg2.IntegrityError:
conn.rollback()
else:
conn.commit()
cur.close()
except Exception , e:
print 'ERROR:', e[0]

Categories