使用多对多关系时sqlalchemy完整性错误

时间:2018-03-25 16:58:51

标签: python sqlalchemy many-to-many

我正在编写应用程序以在MySQL中存储泄露的数据库和哈希值。我想节省一些空间,所以我发现在Hashes表中只存储唯一的哈希并从DBList表中添加引用可能是个好主意。换句话说,如果我想获得属于db_id=1的所有哈希值,我应该使用关联表来请求它们。

出于测试目的,我已经创建了这些文件:

我的问题是,只有当我插入唯一的哈希值时,才会正确填充名为dbtohash的关联表。如果我尝试为DB创建不同的名称并使用相同的哈希表(regex_test.txt),则会引发IntegrityError异常。我该如何解决这个问题?

编辑:根据评论中的建议。这是我的代码的相关部分。这就是我创建多对多关系和关联表的方法:

dbtohash = db.Table(
    'dbtohash',
    db.Column(
        'hash_id',
        db.Integer,
        db.ForeignKey('Hashes.hash_id')),
    db.Column(
        'db_id',
        db.Integer,
        db.ForeignKey('DBList.db_id')))

class DBList(db.Model):
    __tablename__ = 'DBList'
    db_id = db.Column(db.Integer, primary_key=True)
    db_name = db.Column(db.String(128), index=True, unique=True)

class Hashes(db.Model):
    __tablename__ = 'Hashes'
    hash_id = db.Column(db.Integer, primary_key=True)
    hash_val = db.Column(db.String(1024), unique=True)
    hash_salt = db.Column(db.String(256))
    hash_plain = db.Column(db.String(256))
    subscriptions = db.relationship(
        'DBList', secondary=dbtohash, backref=db.backref(
            'dbtohashref', lazy='dynamic'))

这就是我向其中插入数据的方式:

新列表

# if we have some matched hashes...
if len(hash_pass) > 0:
    # create new list
    newlist = DBList(
        db_name = '{}_{}'.format('db', datetime.utcnow()),
    )
    print('newlist: {}'.format(newlist))
    # try to insert DB name to DBList table, raise exception if name is taken
    try:
        db.session.add(newlist)
        db.session.commit()
        db.session.flush()
    except IntegrityError:
        db.session.rollback()
        print('this DB name is taken, choose another one', 'danger')

将哈希值插入DB

failed=[]
for hash in hash_pass:
    inserthash = Hashes (
        hash_val = hash,
    )
    try:
        db.session.add(inserthash)
        db.session.commit()
        db.session.flush()
        hashid=inserthash.hash_id
    except IntegrityError:
        db.session.rollback()
        failed.append(hash)
        hashid=db.session.query(Hashes.hash_id).filter_by(hash_val=hash).one()[0]
    # fill up association table
    newlist.dbtohashref.append(inserthash)
    db.session.commit()
if failed:
    print('failed: {}'.format(failed))

有问题的行是:newlist.dbtohashref.append(inserthash)

编辑2:附加完整跟踪

Traceback (most recent call last):
  File "mydb.py", line 88, in <module>
    db.session.commit()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 153, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 943, in commit
    self.transaction.commit()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 467, in commit
    self._prepare_impl()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 447, in _prepare_impl
    self.session.flush()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2254, in flush
    self._flush(objects)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2380, in _flush
    transaction.rollback(_capture_exception=True)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2344, in _flush
    flush_context.execute()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 391, in execute
    rec.execute(self)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 556, in execute
    uow
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 181, in save_obj
    mapper, table, insert)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 866, in _emit_insert_statements
    execute(statement, params)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 948, in execute
    return meth(self, multiparams, params)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 269, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1060, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1200, in _execute_context
    context)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1413, in _handle_dbapi_exception
    exc_info
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 203, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context
    context)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 507, in do_execute
    cursor.execute(statement, parameters)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/cursors.py", line 165, in execute
    result = self._query(query)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/cursors.py", line 321, in _query
    conn.query(q)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/connections.py", line 860, in query
    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/connections.py", line 1061, in _read_query_result
    result.read()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/connections.py", line 1349, in read
    first_packet = self.connection._read_packet()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/connections.py", line 1018, in _read_packet
    packet.check_error()
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/connections.py", line 384, in check_error
    err.raise_mysql_exception(self._data)
  File "/home/user/envs/project/local/lib/python2.7/site-packages/pymysql/err.py", line 107, in raise_mysql_exception
    raise errorclass(errno, errval)
sqlalchemy.exc.IntegrityError: (pymysql.err.IntegrityError) (1062, u"Duplicate entry 'd38b70e33d7ae06c1696910eb6f93ca4' for key 'hash_val'") [SQL: u'INSERT INTO `Hashes` (hash_val, hash_salt, hash_plain) VALUES (%(hash_val)s, %(hash_salt)s, %(hash_plain)s)'] [parameters: {'hash_salt': None, 'hash_val': 'd38b70e33d7ae06c1696910eb6f93ca4', 'hash_plain': None}] (Background on this error at: http://sqlalche.me/e/gkpj)

0 个答案:

没有答案