【问题标题】:Python / sqlite - Only committing last if statementPython / sqlite - 仅提交最后一个 if 语句
【发布时间】:2013-11-23 19:53:26
【问题描述】:

在下面的代码中,实际显示在数据库中的唯一提交是找到的最后一个“idn”。 idn 只是一个标识号,用于计算每个客户有多少个机顶盒。因此,如果 idn 1,2 和 3 都存在,它只会在应该正确 1,2 和 3 时将 3 写入 DB。如果 idn 1 是唯一存在的,那么它会被写入。谢谢你的帮助!

    if "STBSINFO||" in line:
        head, sep, tail = line.partition('STBSINFO||')
        idn = idn + 1
        if "|" in tail:
            head, sep, tail = tail.partition('|')
            #Creates the mac address variable from the partition
            mac = head                                    
            if "|" in tail:
                head, sep, tail = tail.partition('|')
                #Gathers the IP of the given set top box
                stbip = head
                if idn == 1:
                    cursor.execute("INSERT OR REPLACE INTO packages (cid, mstb1) VALUES (?,?)", (cid, stbip))
                    conn.commit()
                elif idn == 2:
                    cursor.execute("INSERT OR REPLACE INTO packages (cid, mstb2) VALUES (?,?)", (cid, stbip))
                    conn.commit()
                elif idn == 3:
                    cursor.execute("INSERT OR REPLACE INTO packages (cid, mstb3) VALUES (?,?)", (cid, stbip))
                    conn.commit()
                elif idn == 4:
                    cursor.execute("INSERT OR REPLACE INTO packages (cid, mstb4) VALUES (?,?)", (cid, stbip))
                    conn.commit()

【问题讨论】:

  • 你确定不是插入或替换1,然后插入或替换2(替换1),然后插入或替换- 3(替换 2)?如果您不知道……首先,如果您不想替换值,为什么要使用INSERT OR REPLACE;其次,请发布packages 表的架构,以便其他人可以为您解决。
  • 我正在使用 INSERT OR REPLACE 因为信息可能会因月而异。我从旧系统中获得了一个输出文件,然后使用这个 python 程序来理解它。如果有更好的方法,我愿意接受。为什么 2 上的 INSERT OR REPLACE 会替换 1?它们是表中的不同列。这是我用来创建表的: cursor.execute("""CREATE TABLE packages(cid TEXT, mstb1 TEXT, mstb2 TEXT, mstb3 TEXT, mstb4 TEXT, PRIMARY KEY (cid))
  • 我认为你不明白INSERT OR REPLACE 做了什么。它插入一个全新的行,用您的新行完全替换任何冲突的行。它不会更改现有行中的值。看我的回答。

标签: python sqlite commit


【解决方案1】:

如果cid 是主键,或者对它有一些其他唯一性约束(如您的示例中所示),则不能有多个具有相同cid 的行。因此,当您INSERT OR REPLACE 与前一行具有相同cid 的行时,它只会替换上一行。

例如:

sqlite> CREATE TABLE packages (cid PRIMARY KEY, mstb1, mstb2, mstb3, mstb4);
sqlite> INSERT INTO packages (cid, mstb1) values (1, 1);
sqlite> INSERT OR REPLACE INTO packages (cid, mstb2) values (1, 2);
sqlite> SELECT * FROM packages;
cid|mstb1|mstb2|mstb3|mstb4
1||2||

这正是您的程序中发生的事情。插入行1|1|||,然后用行1||2|| 替换它,然后用行1|||3| 替换它。并不是只写了一行,而是每一行都替换了之前的一行,所以最后,你只需要最后写的那一行。


如果您尝试更新该行,请为此使用 UPDATE 语句,而不是 INSERT OR REPLACE

sqlite> UPDATE packages SET mstb1=1 WHERE cid=1;
sqlite> SELECT * FROM packages;
cid|mstb1|mstb2|mstb3|mstb4
1|1|2||

如果您尝试创建两个单独的行,那么您的架构设置错误;如果您想要两个具有相同cid 的不同行,cid 不能是唯一键。在这种情况下,也许您希望所有五列的集合成为键?

sqlite> CREATE TABLE packages (cid NOT NULL, mstb1, mstb2, mstb3, mstb4, PRIMARY KEY(cid, mstb1, mstb2, mstb3, mstb4));
sqlite> INSERT INTO packages (cid, mstb1) values (1, 1);
sqlite> INSERT INTO packages (cid, mstb2) values (1, 2);
sqlite> SELECT * FROM packages;
cid|mstb1|mstb2|mstb3|mstb4
1|1|||
1||2||

INSERTON CONFLICTUPDATE 上的文档更详细地解释了事情。

但是,我认为您需要一个关于 SQL 数据库的基本教程,然后参考文档才有意义。

【讨论】:

  • 我不希望多行具有相同的 cid。我希望每一行都有一个 cid,然后是可变数量的 mstb,最多 4 个。所以你的最后一个例子是我想要的。我对 SQL 的了解非常有限。我只是边走边学。
  • 我怀疑你真正想要的是规范化你的数据模型:有一个packages 的表,其中只有cid,具有一对一与具有cid, mstbid, valuepackage_whatevers 表有许多关系,前两列是唯一的主键。维基百科有一个good article,但实际上你需要找到有关关系数据库的教程。
  • 我会研究一下,看看我能学到什么。目前,当我从 INSERT OR REPLACE 切换到 INSERT 时,我收到此错误 'IntegrityError: column cid is not unique'
  • @user2716271:嗯,是的,这就是重点。您设计了一个表,该表只能有一行具有相同的cid。如果您尝试INSERT 与相同cid 的行,它将失败。如果您尝试INSERT OR REPLACE 具有相同cid 的行,它将删除旧行以便插入新行。这就是那些声明应该做的。如果您想更新现有的行,没有人可以这样做,这就是为什么有一个单独的UPDATE 语句。我在回答中解释了这一点。
  • 非常感谢您的帮助。我不仅现在可以使用它,而且我觉得我更好地理解了这些 SQL 语句。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2020-04-21
  • 2020-11-15
  • 1970-01-01
  • 2018-10-01
  • 2017-10-23
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多