4

私の質問を説明する前に、私の問題を説明するのに役立ついくつかのテーブル定義を以下に示します。

-- 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 テーブルには、Type_ID が Member_Types.ID と等しい Member_Infos テーブルに含めることができるレコードの最大数を表す整数を含む Member_Limit 列があります。

私はチェック制約を書くことができましたが、明らかに mysql はチェック制約を実施していません。挿入する前に、member_infos テーブル内のレコード数が <= Member_Types.Member_Limit であることを確認するトリガーを作成したいと思います。例: 上記のデータを使用すると、レコード 4 の Member_Limit = 5 になります。 Type_ID = 4 の Member_Infos テーブルに新しいレコードを挿入しようとすると、Member_Infos テーブル内の Type_ID <= 5 のレコード数がデータが挿入されます。それ以外の場合は拒否されます。アドバイスをいただければ幸いです。

4

4 に答える 4

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)

= 5の場合にチェックしていましたType_ID。これは、カウント基準が満たされていないかどうかを無視し、タイプid = 5のmember_infoのエントリのメンバーの数がmember_typesテーブルに設定された制限よりも少ない場合にのみ挿入します

于 2012-11-09T07:13:24.403 に答える
1

エラーを発生させるには、トリガーでSIGNALステートメントを使用します。

http://dev.mysql.com/doc/refman/5.5/en/signal.htmlを参照してください

于 2012-11-09T10:07:01.013 に答える
1

MySQL では、データベース レベルでこれを行うには、おそらくトリガーが適切な方法です。

ただし、この種のビジネス ルールの適用は、多くの場合、データベースではなくアプリケーション レイヤーで実行する必要があると見なされます。ビジネス ルールには変更の習慣があり、通常はデータベースよりもアプリケーション レイヤーを変更する方が簡単です。また、アプリケーション レイヤー コードの単体テストを記述するのも簡単で、通常はアプリケーション レイヤーをデバッグするのも簡単です。

于 2012-11-09T10:17:08.907 に答える
0

SQLフィドルデモリンク

次の挿入ステートメントを追加して試すことができます

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

このコード全体の最後に。type_id=2に0レコードが許可されているため、この挿入は許可されませんmember_ifostype_id=5同様に、5つのreocrdを挿入した後、挿入時にエラーが発生します。

静的な値ではなく、新しいエントリごとに検証が必要なため、トリガーを追加しました。したがって、トリガーでのみ使用可能なnew.type_idが必要だったため、MySQLConditionalInsertのようなSOに関するいくつかの質問のようにdualが機能するのと同じ質問ではありません。

以下は完全なコードです

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'ください。この例外は、askerの必要な条件で挿入をブロックするために必要です。しかし、改善は高く評価されます。私はそれを整理することができませんでした。

于 2012-11-09T10:57:19.903 に答える