I'm trying to create a simple realtional database using sqlalchemy and mysql. I'm not sure what I'm doing wrong, although I think it could be something to do with the way I'm adding the rows to the table. My models are below and the code that creates all the entries below that.
This is the error I'm getting:
2014-03-12 14:53:52,109 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO:sqlalchemy.engine.base.Engine:BEGIN (implicit)
2014-03-12 14:53:52,139 INFO sqlalchemy.engine.base.Engine INSERT INTO accession_numbers (accession_number, gene) VALUES (%s, %s)
INFO:sqlalchemy.engine.base.Engine:INSERT INTO accession_numbers (accession_number, gene) VALUES (%s, %s)
2014-03-12 14:53:52,140 INFO sqlalchemy.engine.base.Engine (('AB009589', <__main__.Gene object at 0xe8ba090>), ('AB014887', <__main__.Gene object at 0xe220890>), ('AB019534', <__main__.Gene object at 0xe8baf10>), ('AB038490', <__main__.Gene object at 0xe8b8150>), ('AB046409', <__main__.Gene object at 0xe8b86d0>), ('AB051625', <__main__.Gene object at 0xe8b8c50>), ('AB051627', <__main__.Gene object at 0xe8b8ed0>), ('AB060808', <__main__.Gene object at 0xe8dd110>) ... displaying 10 of 1317 total bound parameter sets ... ('EU266531', <__main__.Gene object at 0x15093b50>), ('EU286279', <__main__.Gene object at 0x15093cd0>))
INFO:sqlalchemy.engine.base.Engine:(('AB009589', <__main__.Gene object at 0xe8ba090>), ('AB014887', <__main__.Gene object at 0xe220890>), ('AB019534', <__main__.Gene object at 0xe8baf10>), ('AB038490', <__main__.Gene object at 0xe8b8150>), ('AB046409', <__main__.Gene object at 0xe8b86d0>), ('AB051625', <__main__.Gene object at 0xe8b8c50>), ('AB051627', <__main__.Gene object at 0xe8b8ed0>), ('AB060808', <__main__.Gene object at 0xe8dd110>) ... displaying 10 of 1317 total bound parameter sets ... ('EU266531', <__main__.Gene object at 0x15093b50>), ('EU286279', <__main__.Gene object at 0x15093cd0>))
2014-03-12 14:53:52,143 INFO sqlalchemy.engine.base.Engine ROLLBACK
INFO:sqlalchemy.engine.base.Engine:ROLLBACK
---------------------------------------------------------------------------
IntegrityError Traceback (most recent call last)
<ipython-input-17-96f4786cad50> in <module>()
29 session.add(acc)
30
---> 31 session.commit()
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/session.pyc in commit(self)
719 raise sa_exc.InvalidRequestError("No transaction is begun.")
720
--> 721 self.transaction.commit()
722
723 def prepare(self):
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/session.pyc in commit(self)
352 self._assert_active(prepared_ok=True)
353 if self._state is not PREPARED:
--> 354 self._prepare_impl()
355
356 if self._parent is None or self.nested:
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/session.pyc in _prepare_impl(self)
332 if self.session._is_clean():
333 break
--> 334 self.session.flush()
335 else:
336 raise exc.FlushError(
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/session.pyc in flush(self, objects)
1822 try:
1823 self._flushing = True
-> 1824 self._flush(objects)
1825 finally:
1826 self._flushing = False
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/session.pyc in _flush(self, objects)
1940 except:
1941 with util.safe_reraise():
-> 1942 transaction.rollback(_capture_exception=True)
1943
1944 def is_modified(self, instance, include_collections=True,
/usr/lib64/python2.7/site-packages/sqlalchemy/util/langhelpers.pyc in __exit__(self, type_, value, traceback)
56 exc_type, exc_value, exc_tb = self._exc_info
57 self._exc_info = None # remove potential circular references
---> 58 compat.reraise(exc_type, exc_value, exc_tb)
59 else:
60 self._exc_info = None # remove potential circular references
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/session.pyc in _flush(self, objects)
1904 self._warn_on_events = True
1905 try:
-> 1906 flush_context.execute()
1907 finally:
1908 self._warn_on_events = False
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/unitofwork.pyc in execute(self)
370 self.dependencies,
371 postsort_actions):
--> 372 rec.execute(self)
373
374 def finalize_flush_changes(self):
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/unitofwork.pyc in execute(self, uow)
523 persistence.save_obj(self.mapper,
524 uow.states_for_mapper_hierarchy(self.mapper, False, False),
--> 525 uow
526 )
527
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/persistence.pyc in save_obj(base_mapper, states, uowtransaction, single)
62 _emit_insert_statements(base_mapper, uowtransaction,
63 cached_connections,
---> 64 table, insert)
65
66 _finalize_insert_update_commands(base_mapper, uowtransaction,
/usr/lib64/python2.7/site-packages/sqlalchemy/orm/persistence.pyc in _emit_insert_statements(base_mapper, uowtransaction, cached_connections, table, insert)
539 multiparams = [rec[2] for rec in records]
540 c = cached_connections[connection].\
--> 541 execute(statement, multiparams)
542
543 for (state, state_dict, params, mapper,
/usr/lib64/python2.7/site-packages/sqlalchemy/engine/base.pyc in execute(self, object, *multiparams, **params)
660 object,
661 multiparams,
--> 662 params)
663 else:
664 raise exc.InvalidRequestError(
/usr/lib64/python2.7/site-packages/sqlalchemy/engine/base.pyc in _execute_clauseelement(self, elem, multiparams, params)
759 compiled_sql,
760 distilled_params,
--> 761 compiled_sql, distilled_params
762 )
763 if self._has_events:
/usr/lib64/python2.7/site-packages/sqlalchemy/engine/base.pyc in _execute_context(self, dialect, constructor, statement, parameters, *args)
872 parameters,
873 cursor,
--> 874 context)
875
876 if self._has_events:
/usr/lib64/python2.7/site-packages/sqlalchemy/engine/base.pyc in _handle_dbapi_exception(self, e, statement, parameters, cursor, context)
1022 self.dialect.dbapi.Error,
1023 connection_invalidated=self._is_disconnect),
-> 1024 exc_info
1025 )
1026
/usr/lib64/python2.7/site-packages/sqlalchemy/util/compat.pyc in raise_from_cause(exception, exc_info)
194 # the code line where the issue occurred
195 exc_type, exc_value, exc_tb = exc_info
--> 196 reraise(type(exception), exception, tb=exc_tb)
197
198
/usr/lib64/python2.7/site-packages/sqlalchemy/engine/base.pyc in _execute_context(self, dialect, constructor, statement, parameters, *args)
854 statement,
855 parameters,
--> 856 context)
857 elif not parameters and context.no_parameters:
858 self.dialect.do_execute_no_params(
/usr/lib64/python2.7/site-packages/sqlalchemy/connectors/mysqldb.pyc in do_executemany(self, cursor, statement, parameters, context)
58
59 def do_executemany(self, cursor, statement, parameters, context=None):
---> 60 rowcount = cursor.executemany(statement, parameters)
61 if context is not None:
62 context._rowcount = rowcount
/usr/lib64/python2.7/site-packages/MySQLdb/cursors.pyc in executemany(self, query, args)
204 r = 0
205 for a in args:
--> 206 r = r + self.execute(query, a)
207 return r
208 p = m.start(1)
/usr/lib64/python2.7/site-packages/MySQLdb/cursors.pyc in execute(self, query, args)
172 del tb
173 self.messages.append((exc, value))
--> 174 self.errorhandler(self, exc, value)
175 self._executed = query
176 if not self._defer_warnings: self._warning_check()
/usr/lib64/python2.7/site-packages/MySQLdb/connections.pyc in defaulterrorhandler(***failed resolving arguments***)
34 del cursor
35 del connection
---> 36 raise errorclass, errorvalue
37
38 re_numeric_part = re.compile(r"^(\d+)")
IntegrityError: (IntegrityError) (1452, 'Cannot add or update a child row: a foreign key constraint fails (`chromo9`.`accession_numbers`, CONSTRAINT `accession_numbers_ibfk_1` FOREIGN KEY (`gene`) REFERENCES `genes` (`gene_identifier`))') 'INSERT INTO accession_numbers (accession_number, gene) VALUES (%s, %s)' (('AB009589', <__main__.Gene object at 0xe8ba090>), ('AB014887', <__main__.Gene object at 0xe220890>), ('AB019534', <__main__.Gene object at 0xe8baf10>), ('AB038490', <__main__.Gene object at 0xe8b8150>), ('AB046409', <__main__.Gene object at 0xe8b86d0>), ('AB051625', <__main__.Gene object at 0xe8b8c50>), ('AB051627', <__main__.Gene object at 0xe8b8ed0>), ('AB060808', <__main__.Gene object at 0xe8dd110>) ... displaying 10 of 1317 total bound parameter sets ... ('EU266531', <__main__.Gene object at 0x15093b50>), ('EU286279', <__main__.Gene object at 0x15093cd0>))
my models:
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import ForeignKey
from sqlalchemy.orm import sessionmaker
SETTINGS = {
'DB':{
'USER':'root',
'LOCATION':'localhost',
'PORT':'3306',
'DATABASE_NAME':'chromo9',
},
}
class Settings:
def __init__(self, **attrs):
for key, value in attrs.iteritems():
if type(value) is dict:
attrs[key] = Settings(**value)
self.__dict__.update(attrs)
SETTINGS = Settings(**SETTINGS)
if not hasattr(SETTINGS.DB, 'PASSWD'):
SETTINGS.DB.PASSWD = raw_input('Enter passwd for mysql user {}'.format(SETTINGS.DB.USER))
conn_string = 'mysql+mysqldb://{user}:{passwd}@{location}:{port}'.format(
user = SETTINGS.DB.USER,
passwd = SETTINGS.DB.PASSWD,
location = SETTINGS.DB.LOCATION,
port = SETTINGS.DB.PORT,
)
#engine = create_engine('sqlite:///:memory:', )#echo=True)
engine = create_engine(conn_string, echo=True)
engine.execute('CREATE DATABASE IF NOT EXISTS {}'.format(SETTINGS.DB.DATABASE_NAME))
engine.execute('USE {}'.format(SETTINGS.DB.DATABASE_NAME))
Base = declarative_base()
class Gene(Base):
__tablename__ = 'genes'
gene_identifier= Column(Integer, primary_key=True)
nucleotide_sequence = Column(Text)
chromosome_location = Column(String(8))
class Accession(Base):
__tablename__ = 'accession_numbers'
accession_number = Column(String(8), primary_key=True)
gene = Column(Integer, ForeignKey('genes.gene_identifier'))
class Exon(Base):
__tablename__ = 'exons'
id = Column(Integer, primary_key=True)
start = Column(Integer)
end = Column(Integer)
gene = Column(Integer, ForeignKey('genes.gene_identifier'))
class Protein(Base):
__tablename__ = 'proteins'
id = Column(Integer, primary_key=True)
name = Column(String(128))
sequence = Column(Text)
gene = Column(Integer, ForeignKey('genes.gene_identifier'))
Base.metadata.create_all(engine) # create the tables
Creating all the objects:
Session = sessionmaker(bind=engine)
session = Session()
for record in records:
gene = Gene(gene_identifier=record.gi ,nucleotide_sequence=record.sequence ,chromosome_location=record.locus)
session.add(gene)
for feature in record.features:
if feature.key == 'CDS':
translation, name = None, None
for qualifier in feature.qualifiers:
if qualifier.key == '/translation=':
translation = qualifier.value
if qualifier.key == '/product=':
name = qualifier.value
# create protein object
protein = Protein(name=name, sequence=translation, gene=gene)
session.add(protein)
if feature.key == 'exon':
start, end = feature.location.split('..')
start, end = int(''.join([d for d in start if d.isdigit()])), int(''.join([d for d in end if d.isdigit()]))
exon = Exon(start=start,end=end,gene=gene)
session.add(exon)
for accession in record.accession:
acc = Accession(accession_number=accession, gene=gene)
session.add(acc)
session.commit()
There was a lot to look through, so I'm sure I missed something, but since I'm not sure how much you know about the database you're working with, I'll start with this and hope it helps:
It looks like you're trying to insert an Accession that references a Gene that doesn't exist. That's the Foreign Key that it's complaining about. It looks like you try to create the Gene and the Accession in the same session. You might need to call session.commit() after creating the Gene (and any other objects that are relied upon by later updates). That will put the Gene in the DB, which can then be referenced by the Accession.
That's a bit of a shot in the dark, as I'm not familiar with SQLAlchemy (and have no idea what an Accession is). I'm just relying on my knowledge of SQL here. But the issue is definitely getting any rows into the gene table BEFORE rows in tables that rely on the gene table are inserted.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.