【问题标题】:Cassandra CQL - update (insert) if not equal toCassandra CQL - 如果不等于则更新(插入)
【发布时间】:2018-05-25 01:51:43
【问题描述】:

如果(非键)字段不等于某个字符串或记录不存在,我需要更新(或插入)记录。例如,给定如下内容:

UPDATE mytable SET firstname='John', lastname='Doe' WHERE id='1' IF lastname != 'Doe';

如果姓氏当前不是“Doe”,则更新它,或者如果记录不存在,则更新(插入)它。我的假设是,如果没有记录,IF 条件将产生 true,但显然不是。有其他选择吗?

【问题讨论】:

    标签: if-statement cassandra cql


    【解决方案1】:

    在 Cassandra 中,UPDATE 的行为与 INSERT 语句非常相似,如 Apache CQL 文档中所述:

    "请注意,与 SQL 不同,UPDATE 默认不检查该行是否存在(通过 IF 除外,见下文):如果之前不存在该行,则创建该行,否则更新该行。此外,还有无法知道是否发生了创建或更新。” - CQL Documentation - Update

    我做了一个简单的测试,它确实有效:

    cqlsh:test_keyspace> select * from conditional_updating ;
    
    id | firstname | lastname
    ----+-----------+----------
    
    (0 rows)
    
    cqlsh:test_keyspace> update conditional_updating 
                           set firstname = 'John', 
                               lastname = 'Doe' 
                           WHERE id = 1 IF lastname != 'Doe';
    
     [applied]
    -----------
      True
    
    cqlsh:test_keyspace> select * from conditional_updating ;
    
     id | firstname | lastname
    ----+-----------+----------
      1 |      John |      Doe
    
    (1 rows)
    
    cqlsh:test_keyspace> update conditional_updating 
                           set lastname = 'New' 
                           WHERE id = 1 IF lastname != 'Doe';
    
     [applied] | lastname
    -----------+----------
         False |      Doe
    

    请注意,使用IF 条件不是免费的 在底层它会触发轻量级事务 (LWT)(也称为 Compara 和 SET 的 CAS)。这样的查询需要读取和写入,并且还需要在所有副本之间达成共识,这使得它有点繁琐。

    “但是,请注意,使用 IF 条件会产生不可忽略的性能成本(在内部,将使用 Paxos),因此应谨慎使用。” - CQL Documentation - Update

    如果您有兴趣了解为什么轻量级事务在 Cassandra 中被视为 反模式,我鼓励您查看此处:Lightweight Transactions In Cassandra

    【讨论】:

    • 我不知道为什么我的 UPDATE 没有插入不存在的记录。我已经尝试过与上面相同的方法,并且 [applied] 总是错误的。
    • 您运行的是哪个版本的 cassandra?我的测试是在 3.11.2 上进行的,尽管这应该没什么区别。如果你愿意,我可以用你的版本做一个测试。
    • 我使用的是 2.2 版。
    • 我对 3.0.x 运行了相同的查询,它可以按您所说的那样工作,但不适用于 2.2。如果你也能确认就好了。奇怪的是,我确信它确实在某些时候对 2.2 有效
    • 一旦我有机会确认你对 2.2 的发现,我会做一个快速测试
    【解决方案2】:

    请参阅此文档,因为这是您需要的,并且在 Cassandra UPDAtE 查询中如果不存在则充当插入。 update with condition

    示例:

    UPDATE keyspace_name.table_name
    USING option AND option
    SET assignment, assignment, ...
    WHERE row_specification 
    IF column_name = literal AND column_name = literal . . . 
    IF EXISTS
    

    【讨论】:

    • 我已经参考了那个文档,它没有解释我描述的场景。如果我运行我最初发布的语句 UPDATE mytable SET firstname='John', lastname='Doe' WHERE id='1' IF lastname != 'Doe'; ,如果 id='1' 的记录不存在,则不会创建记录。
    • 您缺少 IF EXISTS 检查,这将根据您的情况产生真或假
    • 我不相信你可以同时使用 IF 和 IF EXISTS。
    • 我说的和你上面说的一样,你可以使用,但你没有使用。
    • 我不认为我们在同一页上。我想要实现的是有一个 single 语句,它可以实现 1)有条件的 IF 更新记录或 2)如果不存在则插入。理想情况下,我不想将其拆分为 2 个语句。
    猜你喜欢
    • 2015-03-25
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多