如何使用Python在SQLite数据库中连接两个表?

时间:2018-06-10 12:33:26

标签: python sql python-3.x sqlite

我有两张桌子:

1)表A包含列:id,c2,c3

2)表B带有列:pid,c2

我想加入它们,对于A.id = B.pid,将A中的列c2和c3与表B中的匹配行连接起来。

pid可以在表B中多次出现,但id在表A中只出现一次。

我看到了其他解决方案,并尝试了这个:

    cursor.execute("""SELECT A.c2, A.c3, B.c2 
           FROM A
           INNER JOIN B 
           ON A.id=B.pid""")       

    conn.commit()

代码已成功执行,但表中未反映任何更改。

如果需要,我可以提供表格和列的实际数据。

更新

我知道SELECT只会选择而不是更新表B中的数据,但我仍然不了解如何编码问题。

3 个答案:

答案 0 :(得分:2)

问题是你正在做一个SELECT,它从你拥有的表中收集你想要的数据。因此,在您的情况下,您从表中获取数据,加入它们并可以从连接中获取结果,但不会发生任何更改。 您需要使用UPDATE或INSERT来影响您拥有的表。

答案 1 :(得分:1)

您可以在sqlite3控制台(或从python)中运行以下内容来复制您正在执行的操作:

create table a_table (
  id int primary key not null,
  c2 int not null,
  c3 int not null
);

create table b_table (
  pid int not null references a_table,
  c2 int not null
);

insert into a_table values (1, 2, 3);
insert into b_table values (1, 4);
insert into b_table values (1, 5);

select a.c2, a.c3, b.c2 from a_table a inner join b_table b on a.id=b.pid;

drop table a_table;
drop table b_table;

id仅在table_a pidtable_b个外键中唯一。 sqlite为每个表都有一个内置的唯一rowid列,因此我们实际上并不需要id中的table_a字段,而是让它坚持您的示例。

您确定pid不唯一且可能多次出现吗?这会使更新table_a的目标与来自table_b的值相混淆 - 在上面的示例中,您希望使用新{{1}更新1中标识为table_a的行} c24的值?或者你正在尝试做别的事情?

如果5中的pid是唯一的,那么您可能只有table_btable_a,而不是从第二个表中更新。

答案 2 :(得分:1)

您的评论中存在歧义“我希望如上所述匹配id和pid,然后将表格A中的c2& c3的匹配行值添加到表格B”。存在(至少)两种可能性:1)表B包含另外的列c3,或者2)表A中的c3的值应该放在表B的列c2中。以下是这两个备选中的每一个的示例代码。

表B具有c3列

insert into B
    (pid, c2, c3)
select
    A.id,
    A.c2,
    A.c3
from
    A
    inner join B on A.id = B.pid 
       and (A.c2 != B.c2 or A.c3 != B.c3)
    ;

join子句的第二部分确保表A中的数据不会复制表B中已有的任何数据。

A.c3的值将作为B.c2

添加

a)因为要将表A的两个不同列插入到表B的同一列中,所以执行此操作的简单方法是使用两个单独的查询。

insert into B
    (pid, c2)
select
    A.id,
    A.c2
from
    A
    inner join B on A.id = B.pid and A.c2 != B.c2
    ;

insert into B
    (pid, c2)
select
    A.id,
    A.c3
from
    A
    inner join B on A.id = B.pid and A.c3 != B.c2
    ;

b)如果在单个查询中执行此操作很重要,则可以在插入表B之前组合表A的c2和c3列。

insert into B
    (pid, c2)
select
    A2.id,
    A2.c2
from
    (select id, c2 from A union select id, c3 as c2 from A) as A2
    inner join B on A2.id = B.pid and A2.c2 != B.c2
    ;