flyEn'blog

所遇问题与解决方案(二)

得到所连接的数据库

django配置如果是如下:

1
2
3
4
5
6
7
8
9
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': ...,
},
'ATOMIC_REQUESTS': True,
}
}

由于主要配置包括在配置文件中,用常规的settings.DATABASES['default']['NAME']或者connection.settings_dict['NAME']无法得到数据库名。

可用sql语句SELECT DATABASE()查询得到:

1
2
3
4
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT DATABASE()")
database_name = cursor.fetchone()[0]

得到某表的所有外键关系表

遇到因为外键关系无法删除某条数据的情况,以下有两种解决:
一:如果你只需删除这条数据,关联这数据的其他数据无关紧要或者无多大影响的话,那就可以直接删。
如下sql:

1
2
3
SET FOREIGN_KEY_CHECKS=0;
DELETE FROM (table_name) WHERE `id` = 1;
SET FOREIGN_KEY_CHECKS=1;

SET FOREIGN_KEY_CHECKS=0;这代表暂时禁用外键检查。
但是与它关联的数据并不会做任何改变,以删除某个用户为例子,如果这样做的话,这个用户的残留死亡数据会留在数据库,可能会导致一些问题。

二:可先删除所有这条数据的关联数据,再将其删除。
以下sql提供哪些表具有你要删除的数据的引用(references)表名与外键的列名,知道这之后你就可以后续进行操作了,遍历查询集后可对每张表删除已知外键id的数据。

1
2
SELECT * FROM information_schema.KEY_COLUMN_USAGE 
WHERE REFERENCED_TABLE_NAME = ' (table_name)';

应该会得到所有database中关联这张表的所有表与列名,如果这样的话再进行过滤database就ok了。

遍历进行删除:

1
2
3
for row in results:
sql = "DELETE FROM {} WHERE {} = {}".format(row[5], row[6], self.id)
cursor.execute(sql)

最后删除该条数据。

事务管理API

报错如下

1
This is forbidden when an 'atomic' block is active.

Django提供了atomic()API来控制数据库事务。
atomic(using=None, savepoint=True)
如果是django内部执行事务,原子性是由数据库的事务操作来界定的。 atomic允许我们在执行代码块时,在数据库层面提供原子性保证。 如果代码块成功完成, 相应的变化会被提交到数据库进行commit;如果执行期间遇到异常,则会将该段代码所涉及的所有更改回滚。

报错是因为在django执行事务的时候在内部调用了transaction.commit()
因为该块将会自动执行此操作。

更根本的是,这里的错误是混合了高级别的事务API(transaction.atomic())和低级别的事务API(transaction.commit())。它们意在相互替代,不能一起使用。

<未完>

Fork me on GitHub