프로시저에서 테이블명 변수로 가져오기 0 9 2,260

by db초보 [MySQL] mysql 프로시저 [2017.08.02 09:26:46]


사용자한테 날짜1,날짜2를 받아서 해당하는 기간에 대해서 데이터를 가져올려고 하는데 문제는 테이블이 월별로 나눠져있습니다

테이블명이 201705, 201706, 201707 이런식이라서 사용자가 201706~201708라고 입력을 하면 테이블을 201706,201707,201708 3개 테이블을 찾아서 데이터를 가져와야되는데.. 어떻게 가져와야될지 몰르겠습니다

우선 프로시저를 보면.. 몇일(da1)~몇일(da2)까지 사용자한테 데이터를 받아서 가져오는 부분이 있습니다

그리고 제 생각에는 달차이를 계산해서 (8-6)+1를 하니 3개 테이블을 찾아야된다 이것까지는 생각을 했는데.. 문제는 테이블명이 동적으로 들어가지를 않습니다

WHILE 돌리면서 임시테이블을 만들어 조인을 하는게 맞는건가요?? 다른방법이 있는건가요??

DELIMITER $$
CREATE PROCEDURE sale(IN _da1 CHAR(7),IN _da2 CHAR(7))
BEGIN
DECLARE i INT DEFAULT 1;
 DECLARE EXIT HANDLER FOR SQLEXCEPTION
   BEGIN
  ROLLBACK;       
 END;
 START TRANSACTION;
WHILE(i<=_co)DO
SET i=i+1;
END WHILE;

SELECT * FROM _da

 COMMIT;
END$$
DELIMITER;

by 마농 [2017.08.02 09:55:41]

미리 Union All 로 뷰를 만들어 놓고, 뷰를 이용해 조회하세요.
월별 테이블이 새로 생성되는 시점에 뷰도 같이 갱신해 주시면 됩니다.


by db초보 [2017.08.02 10:38:12]

인터넷 찾아보니깐 테이블처럼 뷰는 가상으로 만들어서 데이터는 보여주는거라고 되어있는데

동일조건의 동일데이터를 테이블 하나 만드는거하고 뷰 하나만드는거하고 차이점을 잘 몰르겠습니다

db용량차이가 있는건가요??

 

 


by 마농 [2017.08.02 10:50:47]

테이블은 실체(데이터)가 있는거구요.
뷰는 실체가 없습니다. 뷰는 쿼리만 있습니다.
테이블의 값을 보여주는 창문 역할을 하는 것이구요.

-- 1. 뷰 생성
CREATE VIEW v_test
AS
SELECT * FROM t_201701
UNION ALL SELECT * FROM t_201702
UNION ALL SELECT * FROM t_201703
UNION ALL SELECT * FROM t_201704
UNION ALL SELECT * FROM t_201705
UNION ALL SELECT * FROM t_201706
UNION ALL SELECT * FROM t_201707
UNION ALL SELECT * FROM t_201708
-- UNION ALL SELECT * FROM t_201709    -- 다음달 초에 테이블이 생성될 때 추가해야 함
;
-- 2. 뷰 조회
SELECT *
  FROM v_test
 WHERE dt BETWEEN '20170523' AND '20170711'
;

 


by 마농 [2017.08.02 11:16:41]

음 혹시나 해서 테스트를 좀 해 봤는데...
MySQL은 오라클과 다른 실망스런 결과가 나오네요...
오라클의 경우엔 위와 같이 사용하면
  - 조건절이 각각의 UNION 절로 침투하여 인덱스 스캔을 하게 되는데..
MySQL 의 경우엔 조건절이 침투하지 못하네요.
  - 전체 합집합을 만든 후에 조건으로 걸러내네요.
위 방법을 사용하면 성능에 문제가 발생될 듯 합니다.


by jkson [2017.08.02 12:53:59]

마농님 해당 컬럼에 인덱스가 있는데도 불구하고 필터만 되고 조건절 침투는 안 되는 건가요?

mysql은 이상하네요..

그럼 뷰의 효용성도 엄청 떨어질 것이고 인라인뷰나 서브쿼리의 기능 제약도 많을텐데 말이죠.


by jkson [2017.08.02 11:42:23]

mysql 조건절이 안 들어가나보네요.

그냥

SELECT * FROM t_201701 WHERE :FRDT <= '20170131' AND :TODT >= '20170101' AND DT BETWEEN :FRDT AND :TODT
UNION ALL SELECT * FROM t_201702 WHERE :FRDT <= '20170228' AND :TODT >= '20170201' AND DT BETWEEN :FRDT AND :TODT

...

이런 식으로 하면 어떨까요?


by db초보 [2017.08.02 13:47:32]

뷰 만들때 테이블명 뒤에 where조건에 하나씩 넣으라는 말씀이시죠??

그런데 날짜가 동적으로 들어가는거라서 뷰가 생성이 안되지 않아요??

사용자한테 날짜를 입력받는거라서요..


by 마농 [2017.08.02 13:54:08]

뷰는 위와 같은 성능 이슈로 안될 듯 하고
위 방법은 뷰가 아닌 프로시져에서 직접 union 코딩하라는 의미입니다.
마찬가지로 테이블 신규 생성시 프로시져 코드도 함께 수정되어야 합니다.


by jkson [2017.08.02 15:03:33]

위와 같이 만들더라도 위와 같은 패턴으로 개발해서 써야할 곳이 한 두군데가 아니라면

근본적인 해결책은 아닐 것 같구요.

왜 저렇게 테이블을 월마다 생성해서 사용하시는지요?

관리나 성능 목적이라면 mysql도 파티션 테이블 되는 것 같은데요.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입