【问题标题】:SQlite: select with insert if not existSQlite:如果不存在,则使用插入选择
【发布时间】:2012-03-14 01:35:40
【问题描述】:

假设我们定义了一个表:

CREATE TABLE IF NOT EXISTS 信号(sigid INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)

此表最初是空的。 我想通过选择获取给定 namesigid,如果 name 不存在,添加它并获取新的自动增量身份证。

我想使用这个查询,以便在需要时自动生成一个新的 ID,用作另一个表中的外键。我必须注意表演,所以我不能继续:

  1. 检查名称是否存在并使用 SELECT 返回 id
  2. 如果返回的 id 为 null,则使用 INSERT 创建一个新条目
  3. 使用新的 SELECT 再次获取新 ID

是否可以用一个类似 SELECT 的查询来做到这一点?

谢谢!

【问题讨论】:

    标签: sql sqlite select insert


    【解决方案1】:

    如果表格是空的,而您是一个只填一次的人(以后当表格中有数据时,您不需要再次填写),并且您没有太多行, 然后你可以缓存你已经插入的名字并在内存中查找它们。

    我猜这更像是一种评论。

    还有这个用于获取最后插入的 id:

    SELECT last_insert_rowid();
    

    但如果上述情况适用,您可以通过自己分配 id 更快,而不是将其定义为 AUTOINCREMENT。然后您不需要获取最后插入的 id,您只需保留一个计数器和所有插入的名称,并为您找到的每个新名称递增。

    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;
    }
    

    我不知道还能告诉你什么......

    【讨论】:

    • 我已经找到了这个选项,但这不是我想要的。当我询问已存在名称的 id 时,它可能会返回错误的 id。例如,假设按顺序添加“CAT”->id=1“DOG”->id=2“FISH”->id=3。当我发送“CAT”查询时,它会返回 id=3(最后插入的 id),这是错误的 id。
    • 要回答您的评论,我需要查看您的代码,我会这样做:select id from table where name='CAT'
    • 让我们将此查询封装在一个函数 getid(name) 中。按顺序调用 getid("DOG"),getid("CAT"),getid("DOG"),getid("FISH"),getid("CAT"),getid("BUNNY") 应该按顺序 1 返回, 2,1,3,2,4 last_inserted_id 并不总是我想要的。
    • 我没有其他代码,除了我发布的用于创建表格的代码。如果我从 name='CAT' 的表中调用 select id,它将返回一个空结果,并且不会在表中添加记录“CAT”。我需要一个始终返回有效 ID 的查询,最终在插入后获得
    • 基本上,我需要一个 SQL 行,其行为如下:如果信号中存在名称,则返回名称的 id,否则在信号中插入 (null,name) 并返回名称的 id。我需要它在不同的执行中工作,所以我无法缓存添加的 id。我更愿意在单个 SQL 查询中完成。
    【解决方案2】:

    我认为只有一个选择没有。 假设我想将 id_build = 3, hashed_value = 1 插入到大表“崩溃”中。

    示例中的代码首先选择检查该值是否已在表中,如果是则跳过带有where .. is null 的插入,然后从已保存到临时表中检索 id。 示例:

    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;
    

    【讨论】:

      猜你喜欢
      • 2021-10-14
      • 2011-01-13
      • 1970-01-01
      • 2015-03-31
      • 2012-06-01
      • 2022-10-13
      • 1970-01-01
      • 2015-07-18
      • 2014-11-30
      相关资源
      最近更新 更多