MySql条件插入动态值

时间:2012-11-09 05:42:35

标签: mysql sql

所以在我解释我的问题之前,这里有一些表格定义,以帮助说明我的问题:

-- 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表中的记录数是&lt; = Member_Types.Member_Limit。 例如:使用上面的数据,记录4有一个Member_Limit = 5.如果尝试将新记录插入Member_Infos表中 具有Type_ID = 4并且Number_ID <= 5的Member_Infos表中的记录数比插入的数据多,否则它被拒绝。 任何建议都将不胜感激。

4 个答案:

答案 0 :(得分:3)

在插入之前,您可以编写自己的普通查询来检查“约束”,而不是触发器。尝试:

INSERT INTO member_infos
SELECT      1, 'Timothy', 'secret', 'me@myself.com', 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 = 5的member_info中的条目成员数小于设置的限制时才插入你的member_types

答案 1 :(得分:1)

要引发错误,请在触发器中使用SIGNAL语句。

请参阅 http://dev.mysql.com/doc/refman/5.5/en/signal.html

答案 2 :(得分:1)

在MySQL中,触发器可能是在数据库级别执行此操作的正确方法。

但是,强制执行此类业务规则通常被视为应在应用程序层中执行的操作,而不是数据库中的操作。业务规则有改变的习惯,修改应用程序层通常比数据库更容易。为应用程序层代码编写单元测试也更容易,调试应用程序层通常更容易。

答案 3 :(得分:0)

Sql Fiddle Demo Link

您可以尝试添加以下插入声明

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

在整个代码的末尾。您不会被允许此插入,因为type_id=2允许member_ifos的0条记录。类似的,插入五个reocrds后,type_id=5插入时会出错。

我添加了一个触发器,因为您需要针对每个新条目进行验证而不是某些静态值。 因此,如果你需要new.type_id(仅在触发器中可用),那么双关语可以像SO上的某些问题一样工作 MySQL Conditional Insert也不是同一个问题

以下是完整代码

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'。需要此例外,因为它阻止了在提问者所需条件下的插入。但改善将受到赞赏。我无法理清。