MySQLストレージプロセス学習実践


最初の引用:http://tech.e800.com.cn/articles/2009/87/1249616096147_1.
 
Mysqlは5.0からストレージプロセスとtriggerをサポートしています.mysqlが好きな友達にmysqlが好きな理由をあげました.文法的にはPL/SQLと違っていますが、プログラミングをした人は知っています.文法は問題ではありません.鍵は思想です.大体文法を理解した後、変数定義、循環、判断、遊標、異常処理といういくつかの方面から詳しく勉強しました.旅行標識の使い方については、Mysqlが今提供しているのは特別です.PL/SQLほど使いやすいものはありませんが、使用上は大体同じです.旅行標識declare fetch Sersor cursor for seqname、value from syss_を定義します.sequence遊覧入札open fetch SeqCurerを使用します.fetchデータfetch cursor into_seqiname,_value;遊覧標識close fetch SeqCursorを閉じます.しかし、これはすべてcursorに対する操作です.PL/SQLと区別がないですよね.でも、これはMysqlのfetch過程を書くための根本的なものではないということを知っているだけで、他のもっと深い知識も知っています.私たちは本当に良い泳ぎのためのプロシージャを書くことができます.
まずfetchは循環文から離れられないので、循環を調べてみましょう.私は一般的にLoopとwhileを使っていますが、コードが簡単です.ここでLoopを使っています.例fetch SeqLoop:Loopfetch cursor into_seqiname,_value;
end Loop;今は死のサイクルです.まだ退出していない条件です.ここでoracleと違います.OracleのPL/SQLのポインタには暗黙的変数%notfoundがあります.MysqlはErr handerの声明によって判断されます.Mysqlでラベリングがオーバーフローすると、予め定義されたNOT FOUNDのErrrorが現れます.このErrrorを処理して、continueのhandlerを定義すればラクトできます.Mysql ErrohandlerについてはMysqlマニュアルの定義を調べられます.declare fetch SeqOk book lean;define the flags for loop judgemenntdeclareseqiname varhar(50);define the varient for store the datadeclare uvalue bigint(20)declare fetch SeqCuror cursor for seqname,value from syss_sequence;璖璝define the cursordeclare continue handler for NOT FOUND set fetch SeqOk=true;龚define the continue handler for not found flagset fetch SeqOk=false;
open fetch SeqCurorfetch SeqLoop:Loopif fetch SeqOk thenleave fetch SeqLoop;elsefetch cursor into_seqiname,_value;
select_.seqiname,_value;end if;
end Loop;close fetch SeqCuror;
これは完全なプロセスです.ここで考える人は普通ここでstatement blockのscopeによって、statement blockのscopeを実現します.Mysqlでbegin endによってstatement blockを分割します.blockで定義された変数の範囲もこのblockにあります.したがって、ネストされたクルーズサイクルについては、彼らの対応するerror handlerをもう一つ追加して区別することができます.(Mysqlで同じerrorのhandlerは一回しか定義できません.多く定義すれば、compleの過程でduplicate handler definationを提示します.ですので、NOT FOUNDのhanderは一回だけ定義できます.)Begin endでこの中の遊覧標識のNOT FOUNDハンダーを定義します.
declare fetch SeqOk book lean;define the flags for loop judgemenntdeclareseqiname varhar(50);define the varient for store the datadeclare uvalue bigint(20)declare fetch SeqCuror cursor for seqname,value from syss_sequence;璖璝define the cursordeclare continue handler for NOT FOUND set fetch SeqOk=true;龚define the continue handler for not found flagset fetch SeqOk=false;
open fetch SeqCurorfetch SeqLoop:Loopif fetch SeqOk thenleave fetch SeqLoop;elsefetch cursor into_seqiname,_value; begin
declare fetch SeqOk book book default'inner'declare cursor 2 cursor for select....from...;define the cursordeclare continue handler for NOT FOUND set fetch SeqOk=true;龚define the continue handler for not set fetch SeqOk=false; open cursor 2fetch loop 2 loopif fetch SeqOk thenelse
end if;
end loop;close cursor 2end;end if;
end Loop;close fetch SeqCuror;
これでより多くのレベルのサイクルが簡単に実現できますが、oracleのPL/SQLに対して、Mysqlはまだダイナミックなツアーの定義がサポートされていませんので、強いダイナミックでSQLを張り合わせることはまだできませんが、Mysqlの好みに全く影響を与えません.清新で、鉛の塵の上品さを染めないで、同様に無数のmysqlファンを引きつけて、天の蓮葉の尽きることがない碧をつなぐようです.
添付:MysqlはOracleのexecute immediateのようなダイナミックSQLの機能もあります.この機能によって、動的なラベルの欠陥を補う機能がどれぐらいありますか?prepare s 1 for@sql Str;execute s 1 using@conditions 1;複数のパラメータがあれば、コンマでdeallocate prepare s 1を区切ります.手動でリリースするか、またはconnectionがオフになると、serverは自動的に回収されます.
下記は自分で書いた比較的複雑なデータベースにまたがる保存プロセスを提供します.実現した業務は多くないです.コードを見てください.
主に勉強しました.http://dev.mysql.com/doc/refman/5.1/zh/stored-procedures.html.
DROP PROCEDURE IF EXISTS p1;
CREATE PROCEDURE p1()
BEGIN
	DECLARE userIdVarchar1 VARCHAR(255);
	DECLARE userIdInt1 INTEGER;
	DECLARE fetchFlag1 TINYINT DEFAULT 1;
	DECLARE cursor1 CURSOR FOR SELECT fqt.users.userId FROM fqt.users WHERE classId<>'' LIMIT 10;
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET fetchFlag1=0;
	OPEN cursor1;
	cursor1Loop:LOOP
		IF fetchFlag1=0 THEN LEAVE cursor1Loop;
		ELSE
			FETCH cursor1 INTO userIdVarchar1;
			SELECT jchome.jchome_member.uid INTO userIdInt1 FROM jchome.jchome_member WHERE jchome.jchome_member.username=userIdVarchar1;
			BEGIN
				DECLARE userIdVarchar2 VARCHAR(255);
				DECLARE userIdInt2 INTEGER;
				DECLARE fetchFlag2 TINYINT DEFAULT 1;
				DECLARE statusFlag VARCHAR(30) DEFAULT 'OK';
				DECLARE cursor2 CURSOR FOR SELECT fqt.users.userId FROM fqt.users WHERE fqt.users.classId =(SELECT u.classId FROM fqt.users AS u WHERE u.userId=userIdVarchar1) AND fqt.users.userId<>userIdVarchar1;
				DECLARE CONTINUE HANDLER FOR NOT FOUND SET fetchFlag2=0;
				DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET statusFlag='Duplicate Entry';
				OPEN cursor2;
				cursor2Loop:LOOP
					IF fetchFlag2=0 THEN LEAVE cursor2Loop;
					ELSE
						FETCH cursor2 INTO userIdVarchar2;
						SELECT jchome.jchome_member.uid INTO userIdInt2 FROM jchome.jchome_member WHERE jchome.jchome_member.username=userIdVarchar2;
						IF userIdInt2 IS NULL THEN LEAVE cursor2Loop;
						ELSE
							IF statusFlag<>'Duplicate Entry' THEN
								SET statusFlag='OK';
								INSERT INTO jchome.jchome_friend(uid,fuid,fusername,status,gid,note,num,dateline) VALUES (userIdInt1,userIdInt2,userIdVarchar2,1,6,'test',0,0);
								SELECT userIdInt1,userIdInt2,userIdVarchar2;
							ELSE
								SELECT 'Duplicate Entry';
							END IF;
						END IF;
					END IF;
				END LOOP;
				CLOSE cursor2;
			END;
		END IF;
	END LOOP;
	CLOSE cursor1;
END;

CALL p1();
 エラーに対するDECLARE CONTINUE HANDLER FOR SQLSTATE'23000'
参考:http://dev.mysql.com/doc/refman/5.1/zh/error-handling.html
付録B:エラーコードとメッセージ
 
途中でcast関数を使ってvarharをmediumintに変えたいですが、エラーが発生しました.http://dev.mysql.com/doc/refman/5.1/zh/functions.html#cast-functionsを調べてみます.
CAST(expr) AS type)、CONVRT(expr,type)、CONVRT(expr) US ING トランスフィックCAST() とCONVRT() 関数は、1つのタイプの値を取得し、別のタイプの値を生成します.
このタイプ 次の値のうちの一つとすることができます. 
  •  
    BINARY[(N)]
  • CHAR[N]DATE DATETIME DECIMAL SIGNED[INTEGER]TIME UNSIGNED[INTEGER]