SQlite: выберите со вставкой, если не существует - PullRequest
2 голосов
/ 23 февраля 2012

Предположим, у нас есть таблица, определенная с помощью:

CREATE TABLE, ЕСЛИ НЕ СУЩЕСТВУЕТ сигналы (сигид INTEGER PRIMARY KEY AUTOINCREMENT, имя TEXT)

Эта таблица изначальнопустой.Я хотел бы получить sigid для данного имени с выбором, а в случае, если name не существует, добавьте его и получите новый автоинкрементный идентификатор.

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

  1. проверить, присутствует ли имя и вернуть идентификатор с помощью SELECT
  2. , если возвращенный идентификатор равен нулюсоздать новую запись с INSERT
  3. получить новый идентификатор снова с новым SELECT

Возможно ли сделать это сsingle SELECT -подобный запрос?

Спасибо!

Ответы [ 2 ]

1 голос
/ 10 июля 2017

Я думаю, с одним выбором нет. Допустим, я хочу вставить id_build = 3, hashed_value = 1 в большую таблицу 'crash'.

Код в примере сначала делает выбор, чтобы проверить, было ли значение уже в таблице, если да, пропускает вставку с помощью where .. is null, затем извлекает идентификатор из уже сохраненного во временной таблице. пример:

create temporary table if not exists Variablez(Name TEXT primary key on conflict replace, Value TEXT);            --storing vars
insert into Variablez(Name, Value) values ('tmp_id', (select id_crash from crash where hashed_value = "1" ));     --put id if was existing
insert into crash(id_build, hashed_value) select 3, 1 where (select Value from Variablez where Name = 'tmp_id' ) is null; -- insert if not exists

select 
     case
        when (select Value from Variablez where name = 'tmp_id' ) is null then 
            '0'
        else
            '1'
    end 
as existing,
    case
        when (select Value from Variablez where name = 'tmp_id' ) is null then 
            (select id_crash from crash where hashed_value = "1")
        else
            (select Value from Variablez where name = 'tmp_id')
    end 
as id_returned;
0 голосов
/ 23 февраля 2012

, если таблица пуста, и вы заполняете ее всего за один снимок (и вам не нужно делать это позже, когда в таблице есть данные), И у вас не слишком много строк, тогда вы можете просто кешировать имена, которые вы уже вставили, и посмотреть их в памяти.

Это скорее комментарий, я думаю.

есть и это для получения последнего вставленного идентификатора:

SELECT last_insert_rowid();

Но если вышеупомянутое применимо, вы даже быстрее, назначив идентификаторы самостоятельно, а не определяете его как AUTOINCREMENT.Тогда вам не нужно получать последний вставленный идентификатор, вы просто сохраняете счетчик и все вставленные имена и увеличиваете их для каждого найденного вами нового имени.

CREATE TABLE IF NOT EXISTS signals(sigid INTEGER PRIMARY KEY NOT NULL, name TEXT)

 List<String> insertedNames = new List<String>();
 int count = 0;
 while(input.hasNext())
 {
    String name = input.next();
    if( !insertedNames.contains(name) )
    {
       var sql = "insert into table (sigid,name) VALUES (" + count + ", " + name + ")";
       executeSql(sql);
       insertedNames.add(name);
       count++;
    }
 }

отвечая на ваш комментарий

public int getId( string name )
{
   String sql = "select id from table where name='" + name + "'";
   int theIdForTheName = executeAndGetFirstColumnAsInt(sql);
   return theIdForTheName;
}

я не знаю, что еще вам сказать ...

...