Kub*_*uba 4 postgresql null update hstore
我最近被这个“功能”咬了。
如果您的hstore
列未初始化并且您开始向其中添加条目,则它们都会被无声地吞下而不会出错。
这是预期的吗?
create table test_hstore(id int, map hstore);
insert into test_hstore(id,map) values(0, '');
INSERT 0 1
select * from test_hstore ;
id | map
----+-----
0 |
update test_hstore set map = map || hstore('key1', 'value1') where id = 0;
UPDATE 1
select * from test_hstore;
id | map
----+------------------
0 | "key1"=>"value1"
update test_hstore set map = null where id = 0;
UPDATE 1
select * from test_hstore;
id | map
----+--------
0 | (null)
update test_hstore set map = map || hstore('key1', 'value1') where id = 0;
UPDATE 1
select * from test_hstore;
id | map
----+--------
0 | (null)
Run Code Online (Sandbox Code Playgroud)
如果我不能在列上设置非空约束,我可以通过做类似的事情来保护自己吗(这实际上不起作用):
UPDATE test_hstore SET map = (IF map IS NULL
THEN '' || hstore('key1', 'value1')
ELSE map || hstore('key1', 'value1'))
WHERE id = 0;
Run Code Online (Sandbox Code Playgroud)
在 SQL 中,NULL (operator) (value)
通常是NULL
.
这不是 hstore 独有的,而是所有事物的常态。
空字符串''
与 NULL 不同。'' || 'somestring'
是'somestring'
,而NULL || 'somestring'
是NULL
。
对于 也是如此hstore
。就像NULL + 1
是NULL
。
如果这对您来说是个问题,您可能应该存储空hstore
值而不是NULL
并NOT NULL
在列上分配约束。
@Craig 提供了详细的解释和避免该问题的最佳建议:定义列NOT NULL DEFAULT ''
- 每行添加 1 个字节到存储(通常),其中列可以NULL
代替。
对于当前问题的简单、标准的解决方案COALESCE()
是- 就像任何其他数据类型一样NULL
。允许列中存在值是一个完全合理的设计NULL
,您只需正确处理它即可。
你的想法很接近,但这不是 SQL 语言的一部分(无论是在标准 SQL 中还是在 Postgres 中)。其他一些 RDBMS(例如 MySQL)向 SQL 引入了IF
IF
和IFNULL
,但它们没有在标准功能CASE
和COALESCE
.
CREATE TEMP TABLE test_hstore AS SELECT '1'::int AS id, NULL::hstore AS map; -- test table with 1 row UPDATE test_hstore SET map = map || hstore('key1', 'value1') RETURNING *;
编号 | 地图 ----+-------- 1 | (无效的)UPDATE test_hstore SET map = COALESCE(map, '') || hstore('key1', 'value1') RETURNING *;
编号 | 地图 ---+------------------ 1 | “键1”=>“值1”