我使用mysql的用戶創建了一個表。表格的 列是序列,電子郵件,date_created和date_canceled。 主要是序列和im試圖爲電子郵件和date_canceled做一個唯一的索引 - 所以當電子郵件處於活動狀態(從未取消 - 意味着date_canceled爲NULL)不會被插入另一個活動電子郵件或發生這種情況。mysql不允許在唯一索引處爲NULL
我知道它可以與Oracle數據庫,但與MySQL獨特的指數法允許NULL來完成。
任何建議如何處理這個? 謝謝!
我使用mysql的用戶創建了一個表。表格的 列是序列,電子郵件,date_created和date_canceled。 主要是序列和im試圖爲電子郵件和date_canceled做一個唯一的索引 - 所以當電子郵件處於活動狀態(從未取消 - 意味着date_canceled爲NULL)不會被插入另一個活動電子郵件或發生這種情況。mysql不允許在唯一索引處爲NULL
我知道它可以與Oracle數據庫,但與MySQL獨特的指數法允許NULL來完成。
任何建議如何處理這個? 謝謝!
BDB存儲引擎將把NULL
作爲一個獨特的價值,只允許單個NULL
值。
如果允許
NULL
值的列都有一個唯一的索引,只有單一NULL
值是允許的。這與其他存儲引擎 不同,後者允許在唯一索引中使用多個NULL
值。
如果你不想改變你的存儲引擎來獲得這種行爲,你的其他選擇是改變你的表結構來存儲活動的電子郵件,並取消在不同的表電子郵件...創建執行此行爲的觸發器...或爲此列分配active
電子郵件的魔術日期值,並且不再允許NULL
值。
我你的問題的理解是,你希望每個用戶與他們在任何時間關聯的一個有效的電子郵件,也保持用戶的郵件以往的歷史。
解決方案1
在MySQL的5.7.5您可以通過創建生成列,然後把唯一約束上做到這一點; http://mysqlserverteam.com/generated-columns-in-mysql-5-7-5/。 例如
create table UniqueActiveEmailDemo
(
sequence bigint not null auto_increment primary key
, userId bigint not null
, email nvarchar(1024) not null
, date_created timestamp default now()
, date_cancelled datetime
, single_active_mail_per_user bigint as (if(date_cancelled is null, userId, null))
);
alter table UniqueActiveEmailDemo
add unique UK_UniqueActiveEmailDemo_SingleActiveMailPerUser
(single_active_mail_per_user);
由於MySQL允許在一個唯一約束中存在多個空值,其中記錄被取消,所以generate列的值爲空;所以你可以擁有儘可能多的記錄。但是,如果記錄未被取消,則生成的列將返回用戶的ID;這受限於唯一約束,所以如果存在具有相同用戶標識的另一個活動記錄,則唯一約束將引發異常。
解決方案2
的Sql小提琴:http://sqlfiddle.com/#!9/b54dce/2
但是這也適用於早期版本的更清潔的方法是簡單地阻止可空date_cancelled;相反,在未來任何未取消的項目中將其設置爲固定值,然後將user_id和date_cancelled的組合設置爲null;例如這裏
create table UniqueActiveEmailDemo
(
sequence bigint not null auto_increment primary key
, userId bigint not null
, email nvarchar(1024) not null
, date_created timestamp default now()
, date_cancelled datetime not null default '9999-12-31 23:59:59'
);
ALTER TABLE UniqueActiveEmailDemo
ADD UNIQUE UK_UniqueActiveEmailDemo_SingleActiveMailPerUser
(userId, date_cancelled);
9999-12-31 23:59:59
視爲空值;即任何具有該值的記錄都是活動的。where now() between date_active and date_cancelled
上添加active_from
日期和過濾器來解決上述問題;但是您需要添加更多檢查以確保同一用戶的活動窗口不會重疊;這使事情進一步複雜化。, date_cancelled datetime not null default '9999-12-31 23:59:59' check (date_cancelled = '9999-12-31 23:59:59' or date_cancelled <= now())
你嘗試過將'不NULL'你的指數? – 2013-03-22 18:07:30
笨蛋? http://stackoverflow.com/questions/10009219/oracle-constraint-to-allow-null-value-如 – ficuscr 2013-03-22 18:07:53
我想在date_canceled列允許null,因爲這樣我就知道它的活躍... – user2062262 2013-03-22 18:10:13