MySQL 저장 프로 세 스 학습 실천

우선 인용: http://tech.e800.com.cn/articles/2009/87/1249616096147_1.html
 
Mysql 은 5.0 부터 저장 과정 과 trigger 를 지원 하기 시 작 했 습 니 다. my sql 을 좋아 하 는 친구 들 에 게 my sql 을 더 좋아 하 는 이 유 를 주 었 습 니 다. 문법 적 으로 PL / SQL 과 차이 가 있 지만 프로 그래 밍 을 한 사람 은 문법 이 문제 가 아니 라 사상 이라는 것 을 알 고 있 습 니 다. 문법 을 대체적으로 이해 한 후에 변수 정의, 순환, 판단, 커서, 이상 처리 등 몇 가지 측면 에서 상세 하 게 배 웠 습 니 다.커서 사용법 Mysql 은 아직 특별 합 니 다. PL / SQL 만큼 사용 하기 쉽 지 는 않 지만, 대체로 커서 declare fetchSeqCursor cursor for select seqname, value from sys 를 정의 합 니 다.sequence;커서 open fetchSeqCursor 사용 하기;fetch 데이터 fetch cursor intoseqname, _value;커서 close fetchSeqCursor 닫 기;그러나 이것 은 모두 cursor 를 대상 으로 하 는 조작 일 뿐 입 니 다. PL / SQL 과 다 를 것 이 없습니다. 그러나 이것 만 으로 는 Mysql 의 fetch 과정 을 작성 할 수 없고 다른 깊이 있 는 지식 도 알 아야 좋 은 커서 를 사용 하 는 procedure 를 진정 으로 쓸 수 있 습 니 다.
우선 fetch 는 순환 문 구 를 떠 날 수 없습니다. 그러면 순환 문 구 를 먼저 알 아 보 세 요.나 는 보통 Loop 과 while 를 사용 하 는 것 이 비교적 명확 하고 코드 가 간단 하 다 고 생각한다.여기에 Loop 을 예 로 들 면 fetchSeqLoop: Loopfetch cursor intoseqname, _value;
end Loop;현재 데 드 사이클 입 니 다. 종료 조건 이 없습니다. 여기 서 Oacle 과 차이 가 있 습 니 다. Oracle 의 PL / SQL 지침 에는 내 현적 변수% notfound 가 있 습 니 다. Mysql 은 Error handler 의 성명 을 통 해 판단 합 니 다. declare continue handler for Not found (do some action).Mysql 에서 커서 가 넘 칠 때 미리 정 의 된 NOT FOUND 의 Error 가 발생 합 니 다. 우 리 는 이 Error 를 처리 하고 continue 의 handler 를 정의 하면 싱가포르 를 만 들 수 있 습 니 다. Mysql Error handler 는 Mysql 매 뉴 얼 을 조회 하여 flag 를 정의 할 수 있 습 니 다. NOT FOUND 에서 Flag 를 표시 하고 Loop 에서 이 flag 를 순환 을 끝 내 는 판단 으로 싱가포르 를 만 들 수 있 습 니 다.declare fetchSeqOk boolean; ## define the flag for loop judgementdeclare _seqname varchar(50); ## define the varient for store the datadeclare _value bigint(20);declare fetchSeqCursor cursor for select seqname, value from sys_sequence;## define the cursordeclare continue handler for NOT FOUND set fetchSeqOk = true; ## define the continue handler for not found flagset fetchSeqOk = false;
open fetchSeqCursor;fetchSeqLoop:Loopif fetchSeqOk thenleave fetchSeqLoop;elsefetch cursor into _seqname, _value;
select _seqname, _value;end if;
end Loop;close fetchSeqCursor;
이것 이 바로 완전한 과정 싱가포르 입 니 다. 그러면 생각 하 는 사람들 은 보통 여기 서 생각 합 니 다. 만약 에 그렇다면 포 함 된 커서 순환 싱가포르 를 어떻게 하 는 지 여 기 는 statement block 의 scope 에 따라 싱가포르 를 실현 할 수 있 습 니 다. Mysql 에서 begin end 를 통 해 statement block 을 나 눌 수 있 습 니 다. block 에서 정 의 된 변수 범위 도 이 block 에 있 습 니 다.따라서 끼 워 넣 은 커서 순환 에 대해 서 는 begin end 를 하나 더 추가 하여 그들 이 대응 하 는 error handler 를 구분 할 수 있 습 니 다.begin end 에서 이 커서 의 NOT FOUND handler 를 정의 합 니 다.
declare fetchSeqOk boolean; ## define the flag for loop judgementdeclare _seqname varchar(50); ## define the varient for store the datadeclare _value bigint(20);declare fetchSeqCursor cursor for select seqname, value from sys_sequence;## define the cursordeclare continue handler for NOT FOUND set fetchSeqOk = true; ## define the continue handler for not found flagset fetchSeqOk = false;
open fetchSeqCursor;fetchSeqLoop:Loopif fetchSeqOk thenleave fetchSeqLoop;elsefetch cursor into _seqname, _value; begin
declare fetchSeqOk boolean default 'inner';declare cursor2 cursor for select .... from ...;## define the cursordeclare continue handler for NOT FOUND set fetchSeqOk = true; ## define the continue handler for not set fetchSeqOk = false; open cursor2;fetchloop2 loopif fetchSeqOk thenelse
end if;
end loop;close cursor2;end;end if;
end Loop;close fetchSeqCursor;
이렇게 하면 더 많은 차원 의 순환 을 쉽게 실현 할 수 있 습 니 다. 그러나 Oacle 의 PL / SQL 에 비해 Mysql 은 아직 동적 커서 의 정 의 를 지원 하지 않 기 때문에 강력 한 동적 으로 SQL 을 조합 하여 커서 에서 할 수 없습니다. 그러나 이것 은 제 가 Mysql 에 대한 사랑 정도 에 전혀 영향 을 주지 않 습 니 다. 그녀 는 수 줍 은 연꽃 처럼 찬란 한 색채 가 없 지만 심 플 한 톤 이 라 고 생각 합 니 다.맑 고 납 먼지 하나 묻 지 않 은 고아 함 처럼 수많은 my sql 팬 들 을 끌 어 들 이 고 있 습 니까? 마치 하늘 을 잇 는 연잎 이 끝 없 이 푸 르 고 영일 연꽃 이 다른 빨간색 입 니 다.
첨부: Mysql 도 Oracle 의 execute immediate 와 유사 한 동적 SQL 기능 이 있 습 니 다. 이 기능 을 통 해 동적 커서 의 부족 한 점 을 얼마나 보완 할 수 있 습 니까? 싱가포르 set @ sqlStr = 'select * from table where condition 1 =?'prepare s1 for @sqlStr;execute s1 using @condition1; 만약 여러 개의 인자 가 쉼표 로 deallocate prepare s1 을 구분한다 면;수 동 으로 풀 거나 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: 오류 코드 와 메시지
 
중간 에 캐 스 트 함수 로 varchar 를 mediumint 로 바 꾸 려 고 했 는데 결과 가 틀 렸 습 니 다. 나중에 보 니 http://dev.mysql.com/doc/refman/5.1/zh/functions.html#cast-functions
CAST(expr AS type), CONVERT(expr,type) , CONVERT(expr USING transcoding_name)
CAST() CONVERT () 함 수 는 한 유형의 값 을 가 져 오고 다른 유형의 값 을 만 드 는 데 사용 할 수 있 습 니 다.
이 종류 다음 값 중 하나 일 수 있 습 니 다: 
  •  
    BINARY[(N)]

  • CHAR[(N)]
    DATE
    DATETIME
    DECIMAL
    SIGNED [INTEGER]
    TIME
    UNSIGNED [INTEGER]

    좋은 웹페이지 즐겨찾기