最近、この「機能」に噛まれました。
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;
SQLでは、NULL (operator) (value)
は通常NULL
です。
これはhstoreに固有のものではなく、すべての標準です。
空の文字列''
はNULLとは異なります。 '' || 'somestring'
は'somestring'
ですが、NULL || 'somestring'
はNULL
です。
hstore
についても同様です。 NULL + 1
がNULL
であるように。
これが問題である場合は、hstore
ではなく空のNULL
値を格納し、列にNOT NULL
制約を割り当てる必要があります。
@ Craigは、詳細な説明 およびavoid問題:列を定義します_NOT NULL DEFAULT ''
_-列にNULL
を使用できるストレージ(通常)に1行あたり1バイトを追加します。
当面の問題の単純な標準ソリューションは COALESCE()
-NULL
になる可能性のある他のデータ型と同様です。列にNULL
値を許可することは完全に合理的な設計であり、適切に処理する必要があります。
あなたのアイデア 近いですが、それはSQL言語の一部ではありません(標準SQLでもPostgresでも)。 MySQLのような他のいくつかのRDBMSはSQLにIF
IF
とIFNULL
を導入していますが、それらは標準機能に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"