I'm trying to write a recursive function to delete records using mysql-python-client: each time the function call depends on the last returning IntegrityError
message which can be used to create a new sql to be executed. At the beginning, the code ran smoothly, but it stops with an AssertionError
which cause by the err
is not a complete info like:
Cannot delete or update a parent row: a foreign key constraint fails (`db_name`.`a_table_name`, CONSTRAINT `FK_xxx` FOREIGN KEY (`foreign_key_name`) REFERENCES `incomplete_reference_table_name)
.
So, WHY is the error message incomplete and HOW to make it return a full complete message?
Additional Info: I tried with golang>"github.com/go-sql-driver/mysql"
and even navicat IDE the result is all the same. It seems it's a server side BUG?
Update: test result with CLI: test reulst with CLI in text:
mysql> delete from `bnb_system`.`traveler_checkin_handle_record` where `room_id` in (select `id` from `room` where `fk_roomtype_rooms` in (select `id` from `room_type` where `fk_inn_roomtype` in (select `id` from `inn` where landlord_id in (select id from landlord where user_id in (select id from user where tel='15779313733')))));
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`bnb_system`.`concerned_checkin_traveler_check_in_handle_record`, CONSTRAINT `FKc2166ey4rteqht79ahel72scu` FOREIGN KEY (`traveler_check_in_handle_record_id`) REFERENCES `traveler_checkin_handl)
import mysql.connector
import re
host = "some_host"
user = "some_user"
password = "some_pwd"
database = "some_system"
conn = mysql.connector.connect(host=host,
user=user,
password=password,
database=database)
cur = conn.cursor()
org_sql = "some_sql"
def recursive_delete(sql, cur, conn):
sql_post = sql[sql.index('where'):]
try:
print(sql)
cur.execute(sql)
conn.commit()
except mysql.connector.IntegrityError as e:
err = e.msg
print(err)
ss = r'`[\w_]+`'
info = re.findall(ss, err)
assert len(info) == 6, "error message: {}".format(err)
db, table, foreign_key, reference_table, reference_key = info[0], info[1], info[3], info[4], info[5]
new_sql = "delete from {db}.{table} where {foreign_key} in (select {reference_key} from {reference_table} {sql_post})".format(db=db, table=table, foreign_key=foreign_key, reference_key=reference_key, reference_table=reference_table, sql_post=sql_post)
recursive_delete(sql=new_sql, cur=cur, conn=conn)
recursive_delete(sql=org_sql, cur=cur, conn=conn)
Finally, I changed the implementation of how to query the reference tables in information_schema
, that solved the problem.
def recursive_delete(all_sql, cur, conn):
for sql in all_sql[::-1]:
sql_post = sql[sql.index('where'):]
try:
print(sql)
cur.execute(sql)
conn.commit()
except mysql.connector.IntegrityError as e:
err = e.msg
ss = r'`([\w_]+)`'
info = re.findall(ss, err)
db, table, constraint_name, foreign_key = info[0], info[1], info[2], info[3]
sql_reference_table_and_reference_key = 'select REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.KEY_COLUMN_USAGE where TABLE_NAME="{table}" and CONSTRAINT_NAME="{constraint_name}" and COLUMN_NAME="{foreign_key}"'.format(table=table, constraint_name=constraint_name,
foreign_key=foreign_key)
print(sql_reference_table_and_reference_key)
cur.execute(sql_reference_table_and_reference_key)
result = cur.fetchone()
reference_table, reference_key = result[0], result[1]
new_sql = "delete from {db}.{table} where {foreign_key} in (select {reference_key} from {reference_table} {sql_post})".format(db=db, table=table, foreign_key=foreign_key, reference_key=reference_key, reference_table=reference_table, sql_post=sql_post)
sql_strings.append(new_sql)
recursive_delete(all_sql=all_sql, cur=cur, conn=conn)