Подтвердить что ты не робот

SQLite: можно обновить строку или вставить, если она не существует?

Я уверен, что могу проверить, существует ли строка, выбирая ее, но мне интересно, есть ли способ, который я просто не знаю, - довольно простая задача, которая может быть. Эта таблица SQLite выглядит примерно так:

rowID  QID    ANID  value
------ ------ ----- ------
0      axo    1     45
1      axo    2     12

Если комбинация QID и ANID уже существует, это значение должно быть обновлено, если комбинация QID и ANID еще не существует, то она должна быть вставлена. Хотя его достаточно просто написать:

SELECT * where QID = 'axo' and ANID = 3;

И проверьте, существует ли строка, а затем вставка и вставка/обновление. Я не могу помочь, но искать лучший способ. Спасибо заранее!

4b9b3361

Ответ 1

insert содержит информацию о опции REPLACE

INSERT OR REPLACE INTO tabname (QID,ANID,value) VALUES ('axo',3,45)

"ВСТАВИТЬ ИЛИ ЗАМЕНИТЬ" можно сокращать до REPLACE.

Пример в Perl

Пересмотренный пример использования составного первичного ключа

use strict;
use DBI;

### Connect to the database via DBI
my $dbfile = "simple.db";
unlink $dbfile;
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile");

### Create a table
$dbh->do("CREATE TABLE tblData (qid TEXT, anid INTEGER, value INTEGER, PRIMARY KEY(qid, anid))");

### Add some data
my $insert = $dbh->prepare("INSERT INTO tblData (qid,anid,value) VALUES (?,?,?)");

$insert->execute('axo', 1, 45);
$insert->execute('axo', 2, 12);

$insert->finish;

### Update data
my $insert_update = $dbh->prepare("REPLACE INTO tblData (qid,anid,value) VALUES (?,?,?)");

$insert_update->execute('axo', 2, 500);
$insert_update->execute('axo', 10, 500);

$insert_update->finish;

### Print out the data
my $select = $dbh->prepare("SELECT * FROM tblData ORDER BY 1,2");
$select->execute;

while (my @row = $select->fetchrow_array()) {
    printf "Row: %s\n", join(" - ", @row);
}

$select->finish;

$dbh->disconnect;
exit 0;

Производит следующий вывод, демонстрирующий обновление одной строки и вставку другого

Row: axo - 1 - 45
Row: axo - 2 - 500
Row: axo - 10 - 500

Ответ 2

Остерегайтесь: REPLACE на самом деле не соответствует "UPDATE ИЛИ INSERT"... REPLACE заменяет всю строку. Поэтому, если вы не укажете значения для столбца EVERY, вы замените не заданные столбцы на NULL или значения по умолчанию.

В простом примере, таком как, например, выше, это, вероятно, хорошо, но если вы привыкнете использовать REPLACE как "ОБНОВЛЕНИЕ ИЛИ ВСТАВИТЬ", вы будете записывать данные, когда вы забудете указать значение для каждого поля... просто предупреждение из опыта.

Ответ 3

вы можете использовать команду REPLACE. Документы

Ответ 4

В этой конкретной ситуации оказывается, что нет простого решения - по крайней мере, не того, что я смог найти, несмотря на попытки Марка предложить его.

Решение, которое я использовал, может оказаться полезным для кого-то другого, поэтому я размещаю его здесь.

Я определил первичный ключ с несколькими столбцами как QID + ANID и попытаюсь вставить в таблицу. Если эта конкретная комбинация существует, она выдаст код ошибки 23000, который затем я смогу использовать индикатор, который должен быть ОБНОВЛЕНО. Здесь основной смысл (в PHP):

try {
  $DB->exec("INSERT INTO tblData (QID,ANID,value) VALUES ('xxx','x',1)");
}
catch(PDOException $e) {
  if($e->getCode() == 23000) {
    $DB->exec("UPDATE tblData SET value=value+1 WHERE ANID='x' AND QID='xxx'");
  }
}

Фактический код, который я использовал, немного сложнее, используя make/placeholders и обработку ошибки, если код не 23000 и т.д.