我(糟糕地)为自己设计了一个涉及许多关系和继承模型的数据库,如下所示:
class Instrument(db.Model):
__tablename__ = 'instrument'
id = db.Column(db.Integer, primary_key = True)
sn = db.Column(db.String(24), unique = True, index = True)
...
data = db.relationship('Data', backref = 'Instrument', lazy = 'dynamic', cascade = 'all, delete')
sensors = db.relationship('Sensor', backref = 'Instrument', lazy = 'dynamic', cascade = 'all, delete')
class Sensor(db.Model):
__tablename__ = 'sensors'
id = db.Column(db.Integer, primary_key = True)
sn = db.Column(db.String(24), unique = True, index = True)
...
data = db.relationship('SensorData', backref = 'Sensor', lazy = 'dynamic', cascade = 'all, delete')
instr_sn = db.Column(db.String(24), db.ForeignKey('instrument.sn'), index = True)
class SensorTypeB(Sensor):
__tablename__ = 'sensor_type_b'
id = db.Column(db.Integer, db.ForeignKey('sensors.id'), primary_key = True)
extracolumn = db.Column(db.Float)
__mapper_args__ = {'polymorphic_identity': 'sensor_type_b'}
def __init__(self, extracolumn = None, **kwargs):
super(SensorTypeB, self).__init__(**kwargs)
self.extracolumn = extracolumn
class Data(db.Model):
__tablename__ = 'data'
id = db.Column(db.Integer, primary_key = True)
timestamp = db.Column(db.DateTime)
value = db.Column(db.Float)
parameter = db.Column(db.String(24), index = True)
unit = db.Column(db.String(24))
flag = db.Column(db.Boolean)
instr_sn = db.Column(db.String(24), db.ForeignKey('instrument.sn'), index = True)
class SensorData(Data):
__tablename__ = 'sensor_data'
id = db.Column(db.Integer, db.ForeignKey('data.id'), primary_key = True)
sensor_sn = db.Column(db.String(24), db.ForeignKey('sensors.sn'), index = True)
__mapper_args__ = {'polymorphic_identity': 'sensor_data'}
def __init__(self, sensor_sn, **kwargs):
super(SensorData, self).__init__(**kwargs)
self.sensor_sn = sensor_sn
class MetSensorData(SensorData):
__tablename__ = 'met_sensor_data'
id = db.Column(db.Integer, db.ForeignKey('sensor_data.id'), primary_key = True)
raw = db.Column(db.Float)
__mapper_args__ = {'polymorphic_identity': 'met_sensor_data'}
def __init__(self, raw = None, **kwargs):
super(MetSensorData, self).__init__(**kwargs)
self.raw = raw
为简洁起见,我省略了一大块……但可以添加任何可能相关的细节。以这种方式设置它的目的(在我看来)是为了执行以下操作:
- 每个传感器都必须属于一个仪器,但不是每个仪器都必须有一个传感器
- 所有 Instruments 都有数据(
Instrument.data
) - 所有传感器都有数据(
Sensor.data
) - 传感器模型的子类有数据(
SensorTypeB.data
)
一切都按预期工作,直到我尝试从数据库中删除数据点。它在使用 SQLite3 的单元测试中工作得非常好,但是一旦我将它移动到 MySQL,一切都会因类型错误而中断:
IntegrityError: (_mysql_exceptions.IntegrityError) (1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`db_name`.`met
_sensor_data`, CONSTRAINT `met_sensor_data_ibfk_1` FOREIGN KEY (`id`) REFERENCES `sensor_data` (`id`))') [SQL: u'DELETE FROM sensor_data WHE
RE sensor_data.id = %s'] [parameters: (3L,)]
为什么这只发生在 MySQL 而不是 SQLite 上?我该如何修复和/或改进它?这不是有史以来最糟糕的数据库设计吗?
最佳答案
您得到的错误是告诉您您正在尝试删除 SensorData
行,但在这样做时,MetSensorData
中引用它的条目将是孤儿,并且由于 SQLAlchemy 配置 SensorData
和 MetSensorData
之间关系的方式,MetSensorData
中的孤儿是不允许的。
如果您能找到不需要该类的方法,或者使其成为独立模型而不是 SensorData
模型的扩展,那么您的问题就会消失。如果您想保持模型不变,那么您可以向 SensorData
外键添加一个级联子句,指示数据库删除孤立行而不是提示它。我尚未对其进行测试以确保这是正确的语法,但我认为您可以按如下方式进行:
id = db.Column(db.Integer, db.ForeignKey('sensor_data.id', ondelete='CASCADE'), primary_key = True)
关于python - 无法删除涉及继承模型和与 Flask-SQLAlchemy 的关系的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34959326/