如何在SQLite中有条件地插入或替换行?

7xzttuei  于 2022-11-15  发布在  SQLite
关注(0)|答案(2)|浏览(627)

我想插入或替换_On_Condition。如果不满足条件,请勿插入或更换。这个是可能的吗?
对于我的项目,我目前有两个数据收集流程。一种是速度很快,但不是什么都能抓住。另一种速度很慢,但什么都能抓住。有了这个快速的过程,我几乎可以实时获得数据。对于速度较慢的应用程序,我会在一天结束时使用批处理程序获取数据。
我的问题是:有时快速进程会在慢速进程之前“完成”一条记录(这意味着它不再需要更新),而在当天晚些时候的夜间批处理过程中,“完整”的记录将被在慢速进程的大量数据中找到的过时的“挂起”记录所取代。
我想要的是一个条件检查,其伪代码如下:

If(record_is_not_complete or does_not_exist) 
{ INSERT or REPLACE; }
Else 
{ do_nothing and move_to_the_next; }

如果我从一个标准的INSERT OR REPLACE示例开始:

INSERT OR REPLACE INTO UserProgress (id, status, level) 
  VALUES (1, 'COMPLETE', 5);

这应该会在UserProgress表中产生一行条目[1,Complete,5]。
如果发生以下情况:

INSERT OR REPLACE INTO UserProgress (id, status, level) 
  VALUES (1, 'PENDING', 4);

我希望它跳过这一点,因为已经有了完整的记录。
我相信这是一个重复的问题。但这是真的吗?这个问题的答案太多了,我不确定哪一个是最好的方法。看看我找到的所有这些例子:
我可以尝试添加CASE语句,我被告知它等同于IF-THEN-ELSE语句。As done in this example.
我可以尝试在VALUES中使用SELECTCOALESCE语句。As done in this example.
我甚至可以尝试使用SELECT WHERE语句。As done in this example.
我可以尝试使用LEFT JOIN语句。As done in this example.
这对SQLite来说是件好事。似乎有多种方法可以剥同一只猫的皮。作为一个新手,我现在很困惑。目前还不清楚我应该使用哪种方法。
我正在寻找一个解决方案,可以在一个SQL语句完成。

  • 更新*

我找到了一个两个事务处理的解决方案。我仍在寻找单一交易解决方案。
这是可行的,但使用了两个事务:

public void Create(IEnumerable<UserProgress> items)
        {
            var sbFields = new StringBuilder();
            sbFields.Append("ID,");
            sbFields.Append("STATUS,");
            sbFields.Append("LEVEL,");

            int numAppended = 3;

            var sbParams = new StringBuilder();
            for (int i = 1; i <= numAppended; i++)
            {
                sbParams.Append("@param");
                sbParams.Append(i);

                if (i < numAppended)
                {
                    sbParams.Append(", ");
                }
            }

            // attempting this solution: https://stackoverflow.com/questions/2251699/sqlite-insert-or-replace-into-vs-update-where

            // first insert the new stuff.
            using (var command = new SQLiteCommand(Db))
            {               

                command.CommandText = "INSERT OR IGNORE INTO USERPROGRESS (" + sbFields + ") VALUES(" + sbParams + ")";

                command.CommandType = CommandType.Text;

                using (var transaction = Db.BeginTransaction())
                {
                    foreach (var user in items)
                    {
                        command.Parameters.Add(new SQLiteParameter("@param1", user.Id));
                        command.Parameters.Add(new SQLiteParameter("@param2", user.Status));
                        command.Parameters.Add(new SQLiteParameter("@param3", user.Level));

                        command.ExecuteNonQuery();
                    }

                    transaction.Commit();
                }
            }

            using (var command = new SQLiteCommand(Db))
            {
                string parameterized = "";

                for (int i = 1; i <= 3; i++)
                {
                    parameterized += _columnNames[i - 1] + "=" + "@param" + i;

                    if (i != 3)
                        parameterized += ",";
                }

                command.CommandText = "UPDATE USERPROGRESS SET " + parameterized + " WHERE ID=@param1 AND STATUS !='COMPLETE'";

                command.CommandType = CommandType.Text;

                using (var transaction = Db.BeginTransaction())
                {
                    foreach (var user in items)
                    {
                        command.Parameters.Add(new SQLiteParameter("@param1", user.Id));
                        command.Parameters.Add(new SQLiteParameter("@param2", user.Status));
                        command.Parameters.Add(new SQLiteParameter("@param3", user.Level));

                        command.ExecuteNonQuery();
                    }

                    transaction.Commit();
                }
            }
        }
esbemjvw

esbemjvw1#

SQL

INSERT OR REPLACE INTO UserProgress (id, status, level) SELECT 'id值', '状态值', '级别值'WHERE NOT EXISTS (SELECT * FROM UserProgress WHERE id = 'id值' AND status = 'COMPLETE');
(其中根据需要插入id值状态值级别值)

演示

Http://www.sqlfiddle.com/#!5/a9b82d/1

说明

EXISTS部分用于查询表中是否存在状态值为'COMPLETE'id相同的行。如果是,则不执行任何操作(由于WHERE NOT)。否则,如果不存在,则插入具有指定id的行,如果存在,则使用指定值更新(由于INSERT OR REPLACE)。

anhgbhbe

anhgbhbe2#

IF语句有三种形式:IF-THEN、IF-THEN-ELSE和IF-THEN-ELSIF。
在SQLite中使用IF语句的语法为:

IF expr THEN statement-list
[ELSIF expr THEN statement-list ]*
[ELSE statement-list]
END IF

链接:https://www.sqliteconcepts.org/pl_if.html

相关问题