퀴즈 낼 실력이 될지 모르겠지만
재미있을것 같아서 한번 내봅니다.
활용 범위를 막 생각했는데..두가지 밖에 생각이 안나네요.
1. CRUD MATRIX 작성시에 (이것만 그려주는 솔루션도 예전에 본적 있습니다.)
2. SQL 작성 툴 개발시 TABLE DESCRIPTION 도우미 모듈.
문제는 간단합니다. SQL문(SELECT 문)에서 TABLE LIST 를 종으로 출력하는 문제입니다.
편의상 테이블을 만드시고 하시는것이 좋을듯합니다.
WITH T as (
select 'SELECT * FROM TAB1, TAB2 WHERE TAB1.COL1 = TAB2.COL2 AND COL1 = (SELECT COL2 FROM TAB3 WHERE TAB3.COL3 IN(SELECT COL4 FROM TAB4))' from dual union all
select 'SELECT (SELECT DEPT_NAME FROM DEPT WHERE DEPT_ID=E.DEPT_ID),EMP_ID FROM EMP' from dual
)
select ~~~ from t ;
SUBSTR(ORG_TXT,1,30) | TABLE_NAME |
SELECT (SELECT DEPT_NAME FROM | DEPT |
SELECT (SELECT DEPT_NAME FROM | EMP |
SELECT * FROM TAB1, TAB2 WHERE | TAB1 |
SELECT * FROM TAB1, TAB2 WHERE | TAB2 |
SELECT * FROM TAB1, TAB2 WHERE | TAB3 |
SELECT * FROM TAB1, TAB2 WHERE | TAB4 |
일단 모든 SQL 이 아닌 SELECT 문장만 있다는 전제입니다. 뭐..다른 SQL 은 select 보다 쉬울거라 생각이 듭니다.
참고로 SELECT 'SELECT * FROM TAB' FROM DUAL 같은 SQL 은 DUAL 만 출력되어야 합니다.
제가 한것도 있지만 좀더 나은 작품이 나올것으로 기대 됩니다. *^^*
모범답안은 마농님이 써 놓으셨네요. 제 답보다 훨씬 깔끔하고 확하네요..
감사드립니다.
여기 퀴즈보고 슬쩍 배운 실력으로 문제를 내봤는데..
파서를 만든다는게..쉬운일이 아니란걸 알았네요.
참고로 약간의 예외상황이 있을수 있습니다..*^^*
많은 분들 감사 드립니다.
출제자의 답]
SELECT ORG_TXT, regexp_substr(replace(nvl(regexp_substr(V1, ',?[^,]+,?', 1, l.lvl),
v1),
','),
'\S+') table_name
FROM (SELECT ORG_TXT,
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
ORG_TXT,'''[^'']+''',' '),
' FROM ','$') ,
' SAMPLE[ (]| WHERE[ (]| CONNECT | GROUP | HAVING[ (]| START |\(|\)',' ₩ '),
'$([^₩]+)₩|.',',\1'),
',{1,}',','),
', +,',',') V1
FROM T) T ,
(select level lvl from dual connect by level <= 10) l
WHERE L.LVL <= LENGTH(V1) - LENGTH(REPLACE(V1, ',')) - 1
ORDER BY ORG_TXT, LVL
참고 :
SELECT
[ hint ]
[ { { DISTINCT | UNIQUE } | ALL } ] select_list FROM { table_reference | join_clause | ( join_clause ) }
[ , { table_reference | join_clause | (join_clause) } ] ...
[ where_clause ]
[ hierarchical_query_clause ]
[ group_by_clause ]
[ HAVING condition ]
[ model_clause ]
보완했습니다. 모든 SQL 적용이 가능하도록 혹시 예외를 확인하셨다면..댓글 부탁 드립니다.
select org_txt org_txt ,
lv ,
regexp_substr(regexp_substr(v, '[^,]+', 1, lv), '[^ ]+') table_name
from (select org_txt, regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(upper(org_txt),'F|W|C', ' '),
'(\\r\\n|\\r|\\n)', ' ') , -- 다중행을 1행으로
'/[^/]*/',' '), -- 주석 제거
'''[^'']*''',' '), -- String 제거
'\(',' ('), -- 괄호 띄어 쓰기
'\)',') '), -- 괄호 띄어 쓰기
' FROM ',' F '), -- FROM 을 F 로
'INSERT.*INTO',' F '), -- INSERT INTO 를 F 로
'SELECT ',' W '), -- SELECT 를 W (SUBQUERY)
'UPDATE ',' F '), -- UPDATE 를 FROM 으로
' TABLE',' C '), -- TABLE 함수는 TABLE이 아님
' SET | UNION | WHERE |GROUP BY | HAVING | CONNECT BY | START WITH | MODEL | SAMPLE( )*\(|USING( )*\(| ON|\)|$', ' W '),
'F([^F|W]+)W|.','C\1'),
'( FULL| LEFT| RIGHT| CROSS| NATURAL| INNER)?( OUTER)? JOIN ', 'C'),
'C{1,}','C'),
'\([^C]+C',''),
'C',',') v
from t),
(select level lv from dual connect by level <= 9)
where lv <= length(v) - length(replace(v, ',')) - 1
order by org_txt, lv
JAVA CODE
concatedTables = orgSqlText.toUpperCase()
.replaceAll("F|W|C", " ")
.replaceAll("(\\r\\n|\\r|\\n)", " ")
.replaceAll("/[^/]*/"," ")
.replaceAll("'[^']*'"," ")
.replaceAll("\\("," (")
.replaceAll("\\)",") ")
.replaceAll(" FROM "," F ")
.replaceAll("INSERT.*INTO"," F ")
.replaceAll("SELECT"," W ") //
.replaceAll("UPDATE "," F ")
.replaceAll(" TABLE"," C ")
.replaceAll(" SET | UNION | WHERE |GROUP BY | HAVING | CONNECT BY | START WITH | MODEL | SAMPLE( )*\\(|USING( )*\\(| ON|\\)|$", " W ")
.replaceAll("F([^F|W]+)W|.","C$1")
.replaceAll("( FULL| LEFT| RIGHT| CROSS| NATURAL| INNER)?( OUTER)? JOIN ", "C")
.replaceAll("C{1,}","C")
.replaceAll("\\([^C]+C","")
.replaceAll("C",",")
;