【问题标题】:SQLite: Combine SELECT and DELETE in one statementSQLite:在一个语句中组合 SELECT 和 DELETE
【发布时间】:2009-10-14 04:30:22
【问题描述】:

我需要像这样运行两条语句:

从 db 中选择数量,其中 ID=5 从 ID=5 的数据库中删除

目前我准备并运行两个不同的语句。我想知道是否有一种方法可以将它组合在一个语句中。

基本上我需要做的就是在删除之前从行中获取一个数量列。

【问题讨论】:

  • 我可能错了,但我不认为你可以。它们不能进行单一更改,因为删除可能会删除您尝试获取的信息。它会破坏数据库的完整性。

标签: sql sqlite


【解决方案1】:

SQLite 不支持对标准 SQL 的这种扩展——您必须使用两个语句,首先是 SELECT,然后是 DELETE。当然,您可以将它们包装在事务中(BEGIN 和 COMMIT 语句之前和之后都会保证​​这一点),以保证原子性和一致性。

【讨论】:

    【解决方案2】:

    如果您只想选择行并一次性删除它们,您可以在delete 语句中使用returning 子句。

    例如:

    delete from myTable returning *
    

    delete 语句具有所有可能的选择功能,例如withwhere,允许选择具有任何逻辑的行。

    【讨论】:

      【解决方案3】:

      假设您的调用线程/进程具有唯一标识符(例如 thread_id),我认为一种可行的方法是在您的表中添加一个标志(例如“handlerid”),即在插入时设置为 null,然后执行:

      update db set handlerid = <my_thread_id> where handlerid is null;
      select * from db where handlerid is not null and handlerid = <my_thread_id>;
      delete from db where handlerid is not null and handlerid = <my_thread_id>;
      

      不确定它与事务相比会如何执行,但想不出任何原因它会变得更糟(甚至可能更好),并且使用这种方法,代码看起来尽可能简单。与事务不同,它不需要您在事务失败的情况下进行循环,以确保处理最近一次 SELECT 时表中的所有未完成元素。

      【讨论】:

        【解决方案4】:

        已经很晚了,但对于未来的访客。就我而言,我确实喜欢下面

        我想删除金额 = 5 的 ID,所以我这样做了

        public void selectAndDelete() {
        
        
                try {
                    SQLiteDatabase db = this.getWritableDatabase();
                    int i=db.delete(table_name, "ID = (select ID from table_name where amount = 5)", null);
        
                    if(i>0)
                    {
                            // I'm inserting here new record
                    }
                } catch (SQLException e) {
        
                }
            }
        

        因此,在您的情况下,您需要根据需要修改 where 条件

        【讨论】:

          【解决方案5】:

          您可以通过用分号分隔两个语句来做到这一点,例如(使用 SQLite 的 .NET 端口):

          using (SQLiteConnection conn = new SQLiteConnection("Data Source=fie.db3"))
          {
            conn.Open();
          
            using (var cmd = conn.CreateCommand())
            {
              cmd.CommandText = "SELECT id FROM fies; DELETE FROM fies WHERE id = 5;";
              using (var reader = cmd.ExecuteReader())
              {
                while (reader.Read())
                {
                  Console.WriteLine(reader[0]);
                }
              }
            }
          }
          

          【讨论】:

          • 所有这一切都会执行一个语句,然后执行另一个。它不会使它成为原子的。另一个进程可以在 SELECT 和 DELETE 之间修改数据库。防止这种情况的唯一方法是将它们包装在事务中。
          • 我已经尝试了组合语句(不是事务性的)并在 SQLite 管理器(Firefox 的附加组件)中运行。这就是我所拥有的:“从 id = 5 的表中选择数量;从 id = 5 的地方删除;”命令已执行,行已删除,但组合语句没有返回任何内容
          • 忘记补充:这是针对 iPhone 嵌入式 SQLite - 所以这可能与 combine 语句不同。可以吗?
          • Leon:是的,这可能是实现上的差异。我用 SQLite.NET 对其进行了测试;它肯定会在那里返回 SELECT 的结果。
          • finnw:所以将它们包装在一个事务中:conn.BeginTransaction()。拥有事务并不会阻止您使用组合的 SQL 语句。
          猜你喜欢
          • 2018-02-16
          • 1970-01-01
          • 2011-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多