PostgreSQL 在跨允許 NULL 值的資料列強制執行唯一性限制時面臨著獨特的挑戰。 多行可能共享相同的非 NULL 值,而僅 NULL 條目不同。 這需要在約束定義中仔細處理 NULL。
PostgreSQL 15 及更高版本:NULLS NOT DISTINCT
解
PostgreSQL 15 及後續版本使用 NULLS NOT DISTINCT
子句簡化了這個過程。當將此子句新增至 UNIQUE 限制時,會將 NULL 值視為等效值。 因此,無論可空列是否包含 NULL,都只能存在具有給定非 NULL 值組合的一行。
<code class="language-sql">ALTER TABLE favorites ADD CONSTRAINT favo_uni UNIQUE NULLS NOT DISTINCT (user_id, menu_id, recipe_id);</code>
PostgreSQL 14 及更早版本:部分索引作為解決方法
對於較舊的 PostgreSQL 版本,建議的方法涉及建立部分索引。 這些索引強制資料子集的唯一性,有效地單獨處理 NULL。 一個索引覆蓋可空列不為 NULL 的行,另一個索引處理可空列為 NULL 的行。
<code class="language-sql">CREATE UNIQUE INDEX favo_3col_uni_idx ON favorites (user_id, menu_id, recipe_id) WHERE menu_id IS NOT NULL; CREATE UNIQUE INDEX favo_2col_uni_idx ON favorites (user_id, recipe_id) WHERE menu_id IS NULL;</code>
重要注意事項
部分索引雖然有效,但可能會限制功能。 它們可以限制外鍵引用和叢集選項。 如果完整索引是必需的,請考慮跨越更廣泛的列集(包括可為空列)的 UNIQUE 限制。
另一個選項,雖然可能不適合所有情況,但為可為空的欄位指派非 NULL 預設值。 這簡化了約束創建,但可能會影響資料完整性,具體取決於應用程式的要求。
最後,一致的命名約定至關重要。 在 PostgreSQL 中使用小寫識別碼可以增強可讀性並避免潛在問題。
以上是如何在 PostgreSQL 中使用可空列建立唯一約束?的詳細內容。更多資訊請關注PHP中文網其他相關文章!