2014-03-12 52 views
1

我正在嘗試使用sqlalchemy和mysql創建一個簡單的realtional數據庫。我不確定我在做什麼錯,儘管我認爲這可能與我向表中添加行的方式有關。我的模型在下面,並創建下面所有條目的代碼。Python Sqlalchemy mysql「無法添加或更新子行:外鍵約束失敗」

這是我得到的錯誤:

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>)) 

我的模型:

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 

創建的所有對象:

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() 

回答

0

有很多翻閱,所以我確定我錯過了一些東西,但是因爲我不確定你對於正在使用的數據庫有多少了解,所以我將從第是,並希望它有幫助:

它看起來像你試圖插入引用不存在的基因的Accession。這是它抱怨的外鍵。看起來您嘗試在同一個會話中創建Gene和Accession。您可能需要在創建Gene(以及稍後更新所依賴的任何其他對象)後調用session.commit()。這將把Gene放入數據庫中,然後可以由Accession引用。

由於我對SQLAlchemy並不熟悉(並且不知道Accession是什麼),這在黑暗中有點難度。我只是依靠我在這裏的SQL知識。但是這個問題肯定是在插入依賴基因表的表中的行之前將任何行插入基因表中。

相關問題