2012-02-15 113 views
5

我正在使用由sqlalchemy第三方制作的现有数据库。然而,我遇到了麻烦,因为表没有主键,更糟的是,它们每行都有重复的元素,所以我不能选择现有的列作为主键。这些表格有两列:都具有非唯一值。Python sqlalchemy:没有主键和重复值的表?

我试图猴子补丁表按http://www.blog.pythonlibrary.org/2010/09/10/sqlalchemy-connecting-to-pre-existing-databases/但显然,这并不工作(见下文)

我当前的代码是(MirnaTable是我的映射类,基本上就没有别的骨架)

connection = create_engine("sqlite:///targets.sqlite") 
metadata = MetaData(bind=connection) 
db_table = Table("miranda", metadata, 
       Column("id", Integer, primary_key=True), 
       autoload=True) 
mapper(MirnaTable, db_table) 
Session = sessionmaker(connection) 
session = Session() 

然后我尝试例如发行

all_records = session.query(MirnaTable).all() 

我也得到

sqlalchemy.exc.OperationalError: (OperationalError) no such column: miranda.id 
u'SELECT miranda.gene_id AS miranda_gene_id, miranda."mature_miRNA" AS 
"miranda_mature_miRNA", miranda.id AS miranda_id \nFROM miranda'() 

所以当然没有找到id列。关于我在做什么的任何想法都是错误的?提前致谢。

编辑:按照要求,这里是从表为例(直接从源码检索):

gene mature_miRNA 
---- ------------- 
80205 hsa-miR-200c 
80205 hsa-miR-200c 
9693 hsa-miR-200c 
9693 hsa-miR-200c 
9881 hsa-miR-200c 
9710 hsa-miR-200c 
9750 hsa-miR-200c 
+0

你能张贴表带有示例数据请? – JackalopeZero 2012-02-15 10:30:32

+0

完成:您现在可以期待什么样的数据样本。 – Einar 2012-02-15 10:39:19

+0

如果没有可用作行标识的内容,ORM将无法正常工作。考虑直接使用表而不将其映射到类。 – 2012-02-15 10:50:49

回答

6

您误解了您引用的帖子。您必须选择现有的列并将其定义为主要。也可以通过全部定义来设置复合主键。在你的情况下,我认为一个基因有几个成熟的microRNA,所以主键可能由(gene_id, mature_miRNA)对组成。由于表中没有更多字段,因此在autoload=True标志中没有必要。

db_table = Table("miranda", metadata, 
       Column("gene_id", Integer, primary_key=True), 
       Column("mature_miRNA", Integer, primary_key=True)) 

我不知道表中字段的类型,所以如果它们不是整数,就适当地改变它们。

+0

它的工作原理很棒。我相应地设置了类型,现在我得到了正确的结果(与使用sqlite3的标准查询进行比较)。 – Einar 2012-02-15 10:52:24

+0

根据您在问题中更新的数据,这些配对也不是唯一的,因此它们不能作为主键。像简单查询这样的ORM的某些部分可以工作,其他一些部分可能因禁用重新加载而被欺骗。但不要指望一切都会奏效。 – 2012-02-15 10:59:28

+0

我主要使用平等和IN(这是一个非常简单的用例),但我会做一些准确的测试以防万一。 – Einar 2012-02-15 12:52:49

0

确保ID列中存在先关闭,然后你曾经尝试都大写和小写。

也可以设置两个主键的表:

Column("id", Integer, primary_key=True), 
Column("secondColumn", Integer, primary_key=True) 

然而,这可能会导致更新异常,如果任何其他行此行完全匹配。您可能最好重新创建表格并插入您自己的PK列

+0

我可以做到这一点,但我会尽量避免这种情况,因为它来自第三方,这意味着将所有存在问题的数据库分叉开来。此外,两列(不包括我试图用猴子打补丁的那一列)都有重复的值(是的,一团糟,但我没有那么做......)。编辑:忘了说,“id”列不存在。我跟着在问题中链接的例子来猴子补丁表(但它没有工作)。 – Einar 2012-02-15 10:29:50

0

更改列ID的rowid的SQLite数据库

db_table = Table("miranda", metadata, 
       Column("id", Integer, primary_key=True), 
       autoload=True) 

修改

db_table = Table("miranda", metadata, 
       Column("rowid", Integer, primary_key=True), 
       autoload=True)