2017-08-30 5 views
2

私は以下の表を持っている:除外制約でIS NOT DISTINCT FROMを使用できますか?

CREATE TABLE claim (
    claim_number TEXT NOT NULL, 
    line_id TEXT, 
    process TEXT NOT NULL 
); 

私はclaim_numberとLINE_IDの組み合わせは常に一意になるように、それに制約を追加します。

ほとんどの場合、line_idはnullであり、その請求番号の行は1つだけです。場合によっては、指定されたclaim_numberに複数の行があり、その場合、line_idには常に値が含まれます。ここでの目標は、プロセス列を更新できるように、INSERT...ON CONFLICT DO UPDATEステートメントで競合ターゲットとして使用できるように、(claim_number、line_id)コンボで一意の組み合わせを強制する制約を持つことです。 UNIQUE制約はNULL = NULLを評価しないため意味を持ちませんが、必要ではありません。

私は、次のような排他制約を追加しようとしている:除外制約でIS NOT DISTINCT FROMを使用する方法はあり

ERROR: syntax error at or near "IS" 

ALTER TABLE claim 
ADD EXCLUDE (claim_number WITH =, 
       line_id WITH IS NOT DISTINCT FROM); 

しかし、それはで失敗?

+3

WhyisがNULL可能にLINE_ID?それはなぜテキストですか? (数字のようです) – wildplasser

+1

単純な回避策は、アプリケーションで処理するNULL値に相当するデフォルト値を定義することです。また、なぜそれらの列がTEXTであるのか不思議です... –

+0

@wildplasser先行ゼロを持つ値が変更されないように、すべてのIDをTEXTとして常に置きます。たとえば、009543219などのSSNは、先行ゼロを失うため、INTEGERとして格納しないでください。また、claim_numberのデータは英数字です。基本的に、私が数学をしていないなら、数字ではないはずです。 –

答えて

0

MSSQL Serverでは、これはフィルタ付き一意索引を使用して行われます。フィルタ述語は、値がNULLでない行のみを索引付けすることです。

私はPostgreSQLの専門家ではないんだけど、グーグルが、それは「部分インデックス」を使用して可能です示していますhttps://www.postgresql.org/docs/current/static/indexes-partial.html

CREATE UNIQUE INDEX ix_claim_lines ON claim (claim_number, line_id) 
    WHERE line_id IS NOT NULL 
+0

テーブル全体をカバーするために問題のインデックスが必要なので、 'ON CONFLICT DO UPDATE'ステートメントでそれが必要に応じて機能するように、その一部だけではありません。 –

+0

@GregoryAreniusこのインデックスは、テーブル全体をカバーします。このインデックスは、 'line_id'が指定されている場合にのみ、' claim_number' + 'line_id'に' UNIQUE'制約を適用するために、検索やクエリのパフォーマンスには使用されません。おそらく、 'ON CONFLICT'を使うよりも良いアプローチがありますか? – Dai

+0

@GregoryArenius:部分インデックスは、( 'claim_1'、' line_1')を2度目に挿入することを防ぎます。しかし、欠点は、部分的なインデックス(除外制約のような)を 'on conflict'節に使うことができないことです。また、部分的な索引を使用して一意の_constraint_を作成することはできません。要するに、これらの行が挿入されないようにすることができますが、その制限を使って 'on conflict'を使うことはできません –

関連する問題