将 hstore 条目添加到未初始化 (NULL) 列

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)

Cra*_*ger 7

在 SQL 中,NULL (operator) (value)通常是NULL.

这不是 hstore 独有的,而是所有事物的常态。

空字符串''与 NULL 不同。'' || 'somestring''somestring',而NULL || 'somestring'NULL

对于 也是如此hstore。就像NULL + 1NULL

如果这对您来说是个问题,您可能应该存储空hstore值而不是NULLNOT NULL在列上分配约束。


Erw*_*ter 6

@Craig 提供了详细的解释和避免该问题的最佳建议:定义列NOT NULL DEFAULT ''- 每行添加 1 个字节到存储(通常),其中列可以NULL代替。

对于当前问题的简单、标准的解决方案COALESCE()是- 就像任何其他数据类型一样NULL。允许列中存在值是一个完全合理的设计NULL,您只需正确处理它即可。

你的想法IF很接近,但这不是 SQL 语言的一部分(无论是在标准 SQL 中还是在 Postgres 中)。其他一些 RDBMS(例如 MySQL)向 SQL 引入了IFIFNULL,但它们没有在标准功能CASECOALESCE.

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”

db<>在这里
摆弄 旧的sqlfiddle