Как условно вставить или заменить строку в SQLite?
я хотел бы вставить или replace_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
заявление. как сделано в этом примере.
я могу попытаться использовать SELECT
или COALESCE
заявление в VALUES
. как сделано в этом примере.
я даже могу попытаться использовать SELECT WHERE
заявление. как сделано в этом примере.
я могу попытаться использовать LEFT JOIN
заявление. как сделано в этом примере.
что отлично подходит для SQLite. Существует несколько способов шкура той же кошки. Будучи новичком, я сейчас в замешательстве. Не ясно, какой подход я должен использовать.
я ищу решение, которое можно сделать в одной инструкции sql.
* UPDATE*
я нашел решение для двух транзакций. Я все еще ищу решение для одной транзакции.
это работает, но использует две операции:
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 ответов
среда SQL
INSERT OR REPLACE INTO UserProgress (id, status, level)
SELECT
значение id, '
значение',
уровень стоимости
WHERE NOT EXISTS (SELECT * FROM UserProgress
WHERE id =
значение idAND status = 'COMPLETE');
(где значение id, значение и уровень стоимости вставляются как уместно)
демо
http://www.sqlfiddle.com#!5 / a9b82d/1
объяснение
на EXISTS
часть используется, чтобы узнать, есть ли существующая строка в таблице с тем же id
чье значение состояния 'COMPLETE'
. Если это условие соответствует, ничего не делается (из-за WHERE NOT
). В противном случае строка с указанным id
вставляется, если нет или обновляется с указанными значениями, если они присутствуют (из-за INSERT OR REPLACE
).
существует три формы операторов IF: IF-THEN, IF-THEN-ELSE и IF-THEN-ELSIF.
синтаксис использования оператора If в SQLite:
IF expr THEN statement-list
[ELSIF expr THEN statement-list ]*
[ELSE statement-list]
END IF