我(很差)设计了一个包含许多关系和继承模型的数据库,如下所示:
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
我遗漏了很多东西,但是可以添加任何可能相关的细节。以这种方式(在我看来)设置它的目的是做以下事情:
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上?我该如何修复和/或改进它?这不是有史以来最糟糕的DB设计吗?
答案 0 :(得分:1)
您收到的错误是告诉您正在尝试删除SensorData
行,但这样做会导致引用它的MetSensorData
中的条目成为孤立的,并且由于方式SQLAlchemy配置SensorData
和MetSensorData
之间的关系,MetSensorData
中的孤儿不被允许。
如果您可以找到一种不需要该类的方法,或者使其成为独立模型而不是SensorData
模型的扩展,那么您的问题就会消失。如果要保持模型不变,则可以向SensorData
外键添加一个cascade子句,指示数据库删除孤立行而不是抱怨它。我没有测试它以确保这是正确的语法,但我认为你会这样做:
id = db.Column(db.Integer, db.ForeignKey('sensor_data.id', ondelete='CASCADE'), primary_key = True)