我想插入或替换_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
中使用SELECT
或COALESCE
语句。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();
}
}
}
2条答案
按热度按时间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
)。anhgbhbe2#
IF语句有三种形式:IF-THEN、IF-THEN-ELSE和IF-THEN-ELSIF。
在SQLite中使用IF语句的语法为:
链接:https://www.sqliteconcepts.org/pl_if.html