2016-05-29 68 views
1

我有一個很長的數據庫字段(2083個字符),因此我無法在MySQL中爲它設置UNIQUE約束。爲MySQL數據庫中的long varchar字段強制使用唯一值

我試過修改存儲過程,所以我可以檢查試圖插入的值是否是唯一的,如果不是,則停止插入。但是,存儲過程總是錯誤。我已經嘗試了很多不同的語法。這真是奇怪,存儲過程很好,只有if語句或插入,但不與兩者。

感謝任何幫助。

BEGIN 
SET @insertedid := 0; 
SET @alreadyfound := 0; 
SELECT COUNT(lref_id) FROM listing_referrers WHERE lref_referring_url=in_lref_referring_url INTO @alreadyfound; 

IF (@alreadyfound = 0) THEN 
BEGIN 
    INSERT INTO listing_referrers (lref_listing_id,lref_referring_url,lref_createdby_userid,lref_created) VALUES (in_lref_listing_id, in_lref_referring_url, in_lref_createdby_userid, in_lref_created); 
    SET @insertedid = last_insert_id(); 
END 
SELECT @insertedid; 
END 

回答

1

想法使用觸發器

我不會在這裏使用的方法,但更喜歡使用觸發ON INSERT。您可以在How to prevent using digits in a VARCHAR column using mysql?找到我的答案,它主要將CREATE TRIGGER的想法與SIGNAL的想法相結合,以防萬一檢測到錯誤情況。

所以,你的情況可能然而像

DELIMITER // 

CREATE TRIGGER trg_listing_referrers_unit_ins before insert on listing_referrers 
for each row 
begin 
    IF EXISTS (SELECT * FROM listing_referrers WHERE lref_referring_url = new.lref_referring_url) 
     THEN signal sqlstate '45000' set message_text = 'trying to insert duplicate lref_referring_url'; 
    END IF; 
END 
// 

DELIMITER ; 

注意的是,這需要MySQL 5.5或更高版本。如果你有一個早期版本的MySQL正在運行,這可能會變得很難看......

注意:根據你的表的大小listing_referrers在觸發器中的SELECT聲明可能會變成性能豬。請確保,即使您不能在lref_referring_url上定義具有NON-UNIQUE索引的UNIQUE索引。否則,你最終會得到一個O(n)算法,而不是O(log n)算法,這可能會產生巨大的差異。

想法使用散列鍵列

相反跟蹤唯一在整個VARCHAR,你也可以檢查你的真實密鑰的哈希值的唯一性。例如,你可以在你的表中添加另一個名爲key_hash的列,在其中輸入一個UNIQUE KEY約束(如果你願意的話,你甚至可以把它作爲主鍵)。

插入時,你讓MySQL的計算它的SHA2哈希值上的蒼蠅,像

INSERT INTO listing_referrers (lref_referring_url, key_hash) 
    VALUES("http://server.bogus/mylong/url", SHA2("http://server.bogus/mylong/url", 256)); 

如果你輸入相同的URL兩次,其SHA2值將是相同的,因此唯一關鍵詞key_hash的約束將開始反叛。

由於該函數的密碼驗證屬性collision resistance,所以確保實際上不可能找到兩個具有相同散列值的URL。如果您遇到問題,請將其發送至cryptographers community - 他們非常希望瞭解您的情況(以及許多情報服務)。

注意:如果記錄的URL更改(通過UPDATE),您總是需要確保hash_key也相應更新。否則,你會發瘋。如果這對你來說是一個真正的用例,你可能還想看看MySQL: Computed Column(我不知道,如果這也適用於主鍵列)。

想法限制了字符的唯一性

的如果能夠限制唯一性第一n字符(含n < 255),那麼你可能會發現Storing email VARCHAR(320) as UNIQUE, #1071 - Specified key was too long; max key length is 767有趣。

與限制3072個字符

如果你能確保你的網址將不超過3072個字符,改變字符集來ASCII會增加這個邊界

想法(相比,UTF-8字符256)3072詳細描述在MySQL unique 1500 varchar field error (#1071 - Specified key was too long)

+0

我會在觸發部分使用'IF EXISTS(SELECT ...)THEN ...'。 –

+0

@PaulSpiegel請隨時調整我的答案 - 我已經把它作爲一個社區wiki條目,所以你應該被允許改變它。 – EagleRainbow

+0

哇,非常感謝你的全面回答。哈希鍵列可能最吸引我。如此優雅簡單!我會運行一些測試,並讓你知道我如何繼續。 – ChrisFNZ

相關問題