web-dev-qa-db-ja.com

初期化されていない(NULL)列への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)

列にnull以外の制約を設定できない場合は、そのようなことを実行して自分自身を保護できますか(これは実際には機能しません)。

UPDATE test_hstore SET map = (IF map IS NULL
                                THEN  '' || hstore('key1', 'value1')
                                ELSE map || hstore('key1', 'value1'))
WHERE id = 0;
4
Kuba

SQLでは、NULL (operator) (value)は通常NULLです。

これはhstoreに固有のものではなく、すべての標準です。

空の文字列''はNULLとは異なります。 '' || 'somestring''somestring'ですが、NULL || 'somestring'NULLです。

hstoreについても同様です。 NULL + 1NULLであるように。

これが問題である場合は、hstoreではなく空のNULL値を格納し、列にNOT NULL制約を割り当てる必要があります。

6
Craig Ringer

@ Craigは、詳細な説明 およびavoid問題:列を定義します_NOT NULL DEFAULT ''_-列にNULLを使用できるストレージ(通常)に1行あたり1バイトを追加します。

当面の問題の単純な標準ソリューションCOALESCE() -NULLになる可能性のある他のデータ型と同様です。列にNULL値を許可することは完全に合理的な設計であり、適切に処理する必要があります。

あなたのアイデア IF 近いですが、それはSQL言語の一部ではありません(標準SQLでもPostgresでも)。 MySQLのような他のいくつかのRDBMSはSQLにIFIFNULLを導入していますが、それらは標準機能にnothingを追加します 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 *;_ 
 
 id |マップ
 ---- + -------- 
 1 | (null)
 
 _UPDATE test_hstore SET map = COALESCE(map, '') || hstore('key1', 'value1')
RETURNING *;_ 
 
 id |マップ
 ---- + ------------------ 
 1 | "key1" => "value1" 

db <>フィドル ここ
古い sqlfiddle

4