我在使用Cassandra(2.2.3版)数据库时遇到了奇怪的问题,并在为发送资金功能的简单应用程序编写一些概念证明时使用了静态列。
我的表是:
CREATE TABLE transactions (
profile text,
timestamp timestamp,
amount text,
balance text,
lock int static,
PRIMARY KEY (profile, timestamp)) WITH CLUSTERING ORDER BY (timestamp ASC);
第一步我添加新记录
INSERT INTO transactions (profile, timestamp, amount) VALUES ( 'test_profile', '2015-11-05 15:20:01+0000', '10USD');
然后我想'锁定'当前的用户交易,用他的余额做一些动作。我尝试执行此请求:
UPDATE transactions SET lock = 1 WHERE profile = 'test_profile' IF lock = null;
但是作为cqlsh的结果,我看到了
[applied]
-----------
False
我不明白为什么'False',因为个人资料的当前数据是:
profile | timestamp | lock | amount | balance
--------------+--------------------------+------+--------+---------
test_profile | 2015-11-05 15:20:01+0000 | null | 10USD | null
知道我做错了吗?
更新
阅读Nenad Bozic回答后,我修改了我的例子,以澄清为什么我需要更新条件。完整的代码示例
CREATE TABLE transactions (
profile text,
timestamp timestamp,
amount text,
balance text,
lock int static,
balances map<text,text> static,
PRIMARY KEY (profile, timestamp)
) WITH CLUSTERING ORDER BY (timestamp ASC);
INSERT INTO transactions (profile, timestamp, amount) VALUES ( 'test_profile', '2015-11-05 15:20:01+0000', '1USD');
INSERT INTO transactions (profile, lock) VALUES ('test_profile', 1) IF NOT EXISTS;
BEGIN BATCH
UPDATE transactions SET balances={'USD':'1USD'} WHERE profile='test_profile';
UPDATE transactions SET balance='1USD' WHERE profile='test_profile' AND timestamp='2015-11-05 15:20:01+0000';
DELETE lock FROM transactions WHERE profile='test_profile';
APPLY BATCH;
如果我再次尝试锁定,我会得到
INSERT INTO transactions (profile, lock) VALUES ('test_profile', 1) IF NOT EXISTS;
[applied] | profile | timestamp | balances | lock | amount | balance
-----------+--------------+-----------+-----------------+------+--------+---------
False | test_profile | null | {'USD': '1USD'} | null | null | null
答案 0 :(得分:1)
当您INSERT
时,您没有插入lock
字段,这意味着此字段不存在。 CQLSH或DevCenter中的空表示只是合成糖,使结果看起来像表格数据,但实际上它具有动态键值,并且键值的映射中不存在lock
。查看thrift representation数据非常有用,即使它不再用于了解它是如何存储到磁盘的。
因此,当UPDATE
被触发时,期望列存在以更新它。在您的情况下,lock
列甚至不存在,因此无法更新它。 INSERT
和UPDATE
之间的差异thread也很好。
您有两种解决方案可以完成这项工作:
显式插入
您可以将lock
添加到insert语句并将其设置为null(这与Cassandra不同,而不是将其从insert中排除,因为这样它将获得null值,当您排除它时,此列将不存在于
INSERT INTO transactions (profile, timestamp, amount, lock)
VALUES ( 'test_profile', '2015-11-05 15:20:01+0000', '10USD', null);
在第二个声明中使用insert
由于您是第一次插入第二个语句lock
而不是更新现有值,因为它是该分区的静态列,您可以使用INSERT IF NOT EXISTS
代替UPDATE IF
LWT方式这样做(锁定不存在所以这将会第一次传递并且所有其他时间都失败,因为锁具有值):
INSERT INTO transactions (profile, lock)
VALUES ('test_profile', 1) IF NOT EXISTS;