2012-11-09 57 views
4

所以之前我解釋一下我的問題,這裏有一些精簡表定義來幫助說明我的問題:與動態值的MySql條件插入

-- Holds data about different memberships 
CREATE TABLE IF NOT EXISTS `Member_Types` ( 
`ID` INT UNSIGNED NOT NULL AUTO_INCREMENT, 
`Name` VARCHAR(20) NOT NULL, 
`Description` VARCHAR(255) NOT NULL, 
`Member_Limit` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', 
PRIMARY KEY(`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 


INSERT INTO `Member_Types` (`ID`, `Name`, `Description`, `Member_Limit`) VALUES 
(1, 'General Member', 'Description of this membership.', 00), 
(2, 'Extended Member', 'Description of this membership.', 00), 
(3, 'Premium Member', 'Description of this membership.', 00), 
(4, 'General Administrator', 'Description of this membership.', 05), 
(5, 'Master Administrator', 'Description of this membership.', 01); 

-- Stores the basic data about our site members 
CREATE TABLE IF NOT EXISTS `Member_Infos` ( 
`ID` BIGINT(8) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT, 
`Username` VARCHAR(30) NOT NULL UNIQUE, 
`Password` CHAR(41) NOT NULL, 
`EmailAddr` VARCHAR(100) NOT NULL, 
`Type_ID` INT UNSIGNED NOT NULL, 
`Salt_ID` BIGINT(8) UNSIGNED ZEROFILL NOT NULL, 
PRIMARY KEY(`ID`), 
FOREIGN KEY(`Type_ID`) REFERENCES `Member_Types` (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

的Member_Infos表包含結合Member_Infos.Type_ID =外鍵Member_Types.ID

的Member_Types表具有列Member_Limit其包含表示所述Member_Infos表 可以包含的記錄的最大數目,其中其TYPE_ID等於一個整數Member_Types.ID

我能寫一個檢查約束,但顯然mysql不檢查約束。 我想編寫一個觸發器,檢查member_infos表中的記錄數是否爲< =插入前的Member_Types.Member_Limit。 例如:使用上面的數據,記錄4的Member_Limit = 5。如果嘗試將新記錄插入到Member_Infos表中, 的Type_ID = 4,並且Member_Infos表中的記錄數與Type_ID < = 5比數據被插入,否則被拒絕。 任何意見將不勝感激。

+0

我會說觸發想法可能是最好的。 – Aatch

+0

高度讚賞的問題。希望答案也是:) – Sami

回答

2

代替觸發器,您可以編寫自己的普通查詢以在插入前檢查「約束」。嘗試:

INSERT INTO member_infos 
SELECT  1, 'Timothy', 'secret', '[email protected]', 5, 0 
FROM  dual 
WHERE  (SELECT COUNT(*) FROM member_infos WHERE Type_ID = 5) 
      < 
      (SELECT Member_Limit FROM member_types WHERE ID = 5) 

我已經使用在Type_ID = 5這忽略如果計數標準不被滿足,並插入僅當與類型ID member_info條目的構件的計數= 5小於極限情況,以檢查設置在您的member_types表中

1

在MySQL中,觸發可能是在數據庫級別做的正確方法。

但是,強制執行這種業務規則通常被認爲是您應該在應用程序層而不是數據庫中執行的操作。業務規則有改變的習慣,修改應用層通常比數據庫更容易。爲應用層代碼編寫單元測試也更容易,調試應用層通常更容易。

0

Sql Fiddle Demo Link

您可以通過添加下面的INSERT語句

INSERT INTO `member_infos` (`ID`, `Username`, `Password`, `EmailAddr`, `Type_ID`, 
`Salt_ID`) VALUES (2, 'ewsew', 'ew', 'ewq', 2, 2); 

在這整個代碼結束嘗試。你不會被允許插入,因爲type_id=2被允許0記錄爲member_ifos。相似的,在插入5個Reocr之後,您將在插入時出現錯誤type_id=5

我添加了一個觸發器,因爲您需要驗證每個新條目而不是某個靜態值。 所以它不是一樣的問題,其中雙可以工作像一些問題就像MySQL Conditional Insert因爲你需要新的。TYPE_ID這是隻有在觸發器

以下可用的完整代碼

CREATE TABLE IF NOT EXISTS `member_infos` (
    `ID` bigint(8) unsigned zerofill NOT NULL AUTO_INCREMENT, 
    `Username` varchar(30) NOT NULL, 
    `Password` char(41) NOT NULL, 
    `EmailAddr` varchar(100) NOT NULL, 
    `Type_ID` int(10) unsigned NOT NULL, 
    `Salt_ID` bigint(8) unsigned zerofill NOT NULL, 
    PRIMARY KEY (`ID`), 
    UNIQUE KEY `Username` (`Username`), 
    KEY `Type_ID` (`Type_ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; 

-- Triggers `member_infos` 

DROP TRIGGER IF EXISTS `validate_Member_infos_insert`; 
DELIMITER // 
CREATE TRIGGER `validate_Member_infos_insert` BEFORE INSERT ON `member_infos` 
FOR EACH ROW begin 
declare lim int;declare cnt int; 
select member_limit into lim from member_types where id=new.Type_id; 
select count(*) into cnt from Member_Infos where type_id=new.Type_id; 
if cnt>=lim 
then 
select `Member Limit exeeded for this type` into lim from member_infos; 
end if; 
end 
// 
DELIMITER ; 

CREATE TABLE IF NOT EXISTS `member_types` (
    `ID` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `Name` varchar(20) NOT NULL, 
    `Description` varchar(255) NOT NULL, 
    `Member_Limit` tinyint(2) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ; 

INSERT INTO `member_types` (`ID`, `Name`, `Description`, `Member_Limit`) 
VALUES (1, 'General Member', 'Description of this membership.', 0), 
(2, 'Extended Member', 'Description of this membership.', 0), 
(3, 'Premium Member', 'Description of this membership.', 0), 
(4, 'General Administrato', 'Description of this membership.', 5), 
(5, 'Master Administrator', 'Description of this membership.', 1); 

INSERT INTO `member_infos` (`ID`, `Username`, `Password`, `EmailAddr`, 
`Type_ID`, `Salt_ID`) VALUES (1, 'ewsew', 'ew', 'ewq', 5, 2); 

注:有人可能會提高/刪除錯誤信息#1054 - Unknown column 'Member Limit exeeded for this type' in 'field list'請。這個例外是必要的,因爲它阻止了按照提交者所需條件插入。但改善將不勝感激。我無法整理出來。

+0

「注意:有些人可能會改善/刪除錯誤消息#1054--請在'字段列表'中爲此類型提供未知列'會員限制'。」 ...事實上,引發錯誤的正確方法是使用SIGNAL語句,因爲已經發布在另一個答案中。從我的角度來看,這篇文章提供了更多的實用代碼和小提琴演示(很棒)的細節,但並沒有解決根本問題。 –

+0

非常傷心@MarcAlff。這是我一小時以上的努力。信號可能會拋出錯誤,但根本不能解決根本問題。而我的解決方案需要從我的錯誤消息中刪除前三個單詞。它提供了100%的問題。順便請使用信號解決方案..如果你是非常有信心downvote我的答案。這不是完美的解決方案,但它只有3個字。如果我在'字段列表'中以某種方式顯示錯誤消息爲「此類型的成員限制」,我認爲這將是正確的答案。 (雖然提煉這個錯誤可能需要更多的工作) – Sami