This is an automated email from the ASF dual-hosted git repository.

chengzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 2b3814997f6 Support more plsql statement parse and add plsql parse 
assert logic (#29648)
2b3814997f6 is described below

commit 2b3814997f60c13ba0c91728c66ca4e25fdb01da
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Thu Jan 4 15:12:36 2024 +0800

    Support more plsql statement parse and add plsql parse assert logic (#29648)
    
    * Support more plsql statement parse and add plsql parse assert logic
    
    * fix checkstyle
---
 .../src/main/antlr4/imports/oracle/Keyword.g4      |  68 ++++
 .../oracle/src/main/antlr4/imports/oracle/PLSQL.g4 | 341 +++++++++++++++++--
 .../src/main/antlr4/imports/oracle/Symbol.g4       |   2 +
 .../visitor/statement/OracleStatementVisitor.java  |  79 ++++-
 .../statement/type/OracleDALStatementVisitor.java  |   1 +
 .../statement/type/OracleDDLStatementVisitor.java  | 373 ++++++++++++++++++++-
 .../statement/type/OracleDMLStatementVisitor.java  |  48 ++-
 .../parser/sql/common/enums/SequenceFunction.java  |  30 +-
 .../parser/sql/common/util/ColumnExtractor.java    | 139 +++++++-
 .../sql/common/util/ExpressionExtractUtils.java    | 105 ++++++
 .../parser/sql/common/util/WhereExtractUtils.java  |  14 +
 .../oracle/ddl/OracleCreateFunctionStatement.java  |  15 +
 .../oracle/ddl/OracleCreateProcedureStatement.java |  21 +-
 .../CursorForLoopStatementSegment.java}            |  28 +-
 .../oracle/plsql/ProcedureCallNameSegment.java     |  53 +++
 .../SQLStatementSegment.java}                      |  20 +-
 .../ddl/CreateFunctionStatementHandlerTest.java    |   3 +-
 .../ddl/CreateProcedureStatementHandlerTest.java   |   3 +-
 .../asserts/statement/SQLStatementAssert.java      |   9 +-
 .../statement/plsql/PLSQLStatementAssert.java      | 131 ++++++++
 ...ectedDynamicSqlStatementExpressionSegment.java} |   8 +-
 .../plsql/ExpectedProcedureCallNameSegment.java}   |  17 +-
 .../impl/plsql/ExpectedRoutineName.java}           |  17 +-
 .../impl/plsql/ExpectedSQLStatementSegment.java}   |  17 +-
 .../ddl/CreateFunctionStatementTestCase.java       |  28 ++
 .../ddl/CreateProcedureStatementTestCase.java      |  28 ++
 .../statement/plsql/CreateFunctionTestCase.java    |  54 +++
 .../statement/plsql/CreateProcedureTestCase.java   |  54 +++
 .../main/resources/case/plsql/create-function.xml  |  21 ++
 .../main/resources/case/plsql/create-procedure.xml |  34 ++
 .../sql/supported/plsql/create-function.xml        |  21 ++
 .../sql/supported/plsql/create-procedure.xml       |  21 ++
 32 files changed, 1718 insertions(+), 85 deletions(-)

diff --git 
a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4 
b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
index 0580c89348a..377fbd3871f 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
@@ -839,3 +839,71 @@ AUTONOMOUS_TRANSACTION
 WM_CONCAT
     : W M UL_ C O N C A T
     ;
+
+DECLARE
+    : D E C L A R E
+    ;
+    
+BULK
+    : B U L K
+    ;
+
+COLLECT
+    : C O L L E C T
+    ;    
+
+INSERTING
+    : I N S E R T I N G
+    ;
+    
+UPDATING
+    : U P D A T I N G
+    ;
+    
+DELETING
+    : D E L E T I N G
+    ;
+    
+ROWCOUNT
+    : R O W C O U N T
+    ;
+    
+BULK_ROWCOUNT
+    : B U L K UL_ R O W C O U N T
+    ;
+    
+RAISE
+    : R A I S E
+    ;
+    
+WHILE
+    : W H I L E
+    ;
+    
+GOTO
+    : G O T O
+    ;
+    
+MUTABLE
+    : M U T A B L E
+    ;
+    
+IMMUTABLE
+    : I M M U T A B L E
+    ;
+    
+INDICES
+    : I N D I C E S
+    ;
+    
+PAIRS
+    : P A I R S
+    ;
+    
+PIPE
+    : P I P E
+    ;
+    
+FORALL
+    : F O R A L L
+    ;
diff --git a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4 
b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
index 637ab4ee0e9..b9093f9eb94 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
@@ -17,7 +17,7 @@
 
 grammar PLSQL;
 
-import Keyword, BaseRule, DDLStatement, DMLStatement;
+import Keyword, BaseRule, DDLStatement, DMLStatement, TCLStatement;
 
 call
     : CALL 
@@ -48,10 +48,6 @@ plsqlProcedureSource
     ((defaultCollationClause | invokerRightsClause | accessibleByClause)*)? 
(IS | AS) (callSpec | declareSection? body)
     ;
 
-plsqlBlock
-    : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)* DECLARE declareSection 
body
-    ;
-
 createFunction
     : CREATE (OR REPLACE)? (EDITIONABLE | NONEDITIONABLE)? FUNCTION 
plsqlFunctionSource
     ;
@@ -77,51 +73,336 @@ body
     : BEGIN statement+ (EXCEPTION (exceptionHandler)+)? END (identifier)? SEMI_
     ;
 
-//need add more statement type according to the doc
+// TODO need add more statement type according to the doc
 statement
     : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_ (SIGNED_LEFT_SHIFT_ label 
SIGNED_RIGHT_SHIFT_) *)?
-        (select
-        | update
-        | delete
-        | insert
-        | lockTable
-        | merge
-        | assignmentStatement
+        (assignStatement
         | basicLoopStatement
+        | caseStatement
         | closeStatement
+        | continueStatement
+        | cursorForLoopStatement
+        | executeImmediateStatement
+        | exitStatement
         | fetchStatement
-        | ifStatment
-        | returnStatement
+        | forLoopStatement
+        | forallStatement
+        | gotoStatement
+        | ifStatement
         | nullStatement
-        ) SEMI_
+        | openStatement
+        | openForStatement
+        | pipeRowStatement
+        | plsqlBlock
+        | raiseStatement
+        | returnStatement
+        | selectIntoStatement
+        | sqlStatementInPlsql
+        | procedureCall
+        | whileLoopStatement
+        )
+    ;
+
+assignStatement
+    : assignStatementTarget ASSIGNMENT_OPERATOR_ expression SEMI_
+    ;
+
+assignStatementTarget
+    : collectionVariable=name (LP_ INTEGER_ RP_)?
+    // TODO cursor_variable, out_parameter, scalar_variable
+    | name
+    | placeholder
+    | hostCursorVariable
+    // TODO object.attribute, record_variable.field
+    | attributeName
+    ;
+
+placeholder
+    : COLON_ hostVariable=name (COLON_ indicatorVariable=name)?
+    ;
+
+// TODO PL/SQL grammar more than expr
+expression
+    : expr
+    ;
+
+booleanExpression
+    : NOT? booleanPrimary ((AND | OR) NOT? booleanPrimary)*
     ;
 
 basicLoopStatement
-    : LOOP (statement (EXIT label? (WHEN booleanPrimary)? SEMI_)?)+ END LOOP 
label?
+    : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+    LOOP statement+ END LOOP label? SEMI_
     ;
 
-assignmentStatement
-    : variableName ASSIGNMENT_OPERATOR_ expr
+caseStatement
+    : simpleCaseStatement | searchedCaseStatement
+    ;
+
+simpleCaseStatement
+    : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+    CASE selector=expression
+    (WHEN booleanExpression THEN statement)+
+    (ELSE statement+)?
+    END CASE label? SEMI_
+    ;
+
+searchedCaseStatement
+    : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+    CASE
+    (WHEN booleanExpression THEN statement+)+
+    (ELSE statement+)?
+    END CASE label? SEMI_
     ;
 
 closeStatement
-    : CLOSE cursorName
+    : CLOSE (cursor | cursorVariable | hostCursorVariable) SEMI_
+    ;
+
+continueStatement
+    : CONTINUE label? (WHEN booleanExpression)? SEMI_
+    ;
+
+cursorForLoopStatement
+    : FOR record IN
+    (cursor (LP_ actualCursorParameter (COMMA_? actualCursorParameter)* RP_)?
+    | LP_ select RP_
+    )
+    LOOP statement+ END LOOP label? SEMI_
+    ;
+
+executeImmediateStatement
+    : EXECUTE IMMEDIATE dynamicSqlStmt
+        ((selectIntoClause | bulkCollectIntoClause) plsqlUsingClause?
+        | plsqlUsingClause dynamicReturningClause?
+        | dynamicReturningClause
+        )? SEMI_
+    ;
+
+dynamicReturningClause
+    : (RETURNING | RETURN) (selectIntoClause | bulkCollectIntoClause)
+    ;
+
+exitStatement
+    : EXIT label? (WHEN booleanExpression)? SEMI_
     ;
 
 fetchStatement
-    : FETCH cursorName INTO identifier
+    : FETCH (cursor | cursorVariable | hostCursorVariable)
+    (selectIntoClause | bulkCollectIntoClause (LIMIT expression)?) SEMI_
     ;
 
-ifStatment
-    : IF booleanPrimary THEN statement+ (ELSIF booleanPrimary THEN 
statement+)? (ELSE statement)? END IF
+forLoopStatement
+    : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+    FOR iterator
+        LOOP statement+
+    END LOOP label? SEMI_
     ;
 
-returnStatement
-    : RETURN expr
+iterator
+    : iterandDecl (COMMA_ iterandDecl)* IN iterationCtlSeq
+    ;
+
+iterandDecl
+    : plsIdentifier=identifier (MUTABLE | IMMUTABLE)? constrainedType=dataType?
+    ;
+
+iterationCtlSeq
+    : qualIterationCtl (COMMA_ qualIterationCtl)*
+    ;
+
+qualIterationCtl
+    : REVERSE? iterationCcontrol predClauseSeq
+    ;
+
+iterationCcontrol
+    : steppedControl
+    | singleExpressionControl
+    | valuesOfControl
+    | indicesOfControl
+    | pairsOfControl
+    | cursorIterationControl
+    ;
+
+predClauseSeq
+    : (WHILE booleanExpression)? (WHEN booleanExpression)?
+    ;
+
+steppedControl
+    : lowerBound RANGE_OPERATOR_ upperBound (BY step=expression)?
+    ;
+
+singleExpressionControl
+    : REPEAT? expression
+    ;
+
+valuesOfControl
+    : VALUES OF
+    (expression
+    | cursorVariable
+    | LP_ cursorObject | dynamicSql | sqlStatementInPlsql RP_
+    )
+    ;
+
+indicesOfControl
+    : INDICES OF
+    (expression
+    | cursorVariable
+    | LP_ cursorObject | cursorVariable | dynamicSql | sqlStatementInPlsql RP_
+    )
+    ;
+
+pairsOfControl
+    : PAIRS OF
+    (expression
+    | cursorVariable
+    | LP_ cursorObject | dynamicSql | sqlStatementInPlsql RP_
+    )
+    ;
+
+cursorIterationControl
+    : LP_ cursorObject | cursorVariable | dynamicSql | sqlStatementInPlsql RP_
+    ;
+
+dynamicSql
+    : EXECUTE IMMEDIATE dynamicSqlStmt (USING IN? (bindArgument COMMA_?)* )?
+    ;
+
+cursorObject
+    : variableName
+    ;
+
+forallStatement
+    : FORALL index=name IN boundsClause (SAVE EXCEPTIONS)? dmlStatement SEMI_
+    ;
+
+boundsClause
+    : lowerBound RANGE_OPERATOR_ upperBound
+    | INDICES OF collection=name (BETWEEN lowerBound AND upperBound)?
+    | VALUES OF indexCollection=name
+    ;
+
+lowerBound
+    : expression
+    ;
+
+upperBound
+    : expression
+    ;
+
+dmlStatement
+    : insert | update | delete | merge | dynamicSqlStmt
+    ;
+
+dynamicSqlStmt
+    : expression
+    ;
+
+gotoStatement
+    : GOTO label SEMI_
+    ;
+
+ifStatement
+    : IF booleanExpression THEN statement+
+    (ELSIF booleanExpression THEN statement+)*
+    (ELSE statement+)?
+    END IF SEMI_
     ;
 
 nullStatement
-    : NULL
+    : NULL SEMI_
+    ;
+
+openStatement
+    : OPEN cursor (LP_ actualCursorParameter (COMMA_? actualCursorParameter)* 
RP_)? SEMI_
+    ;
+
+cursor
+    : variableName
+    ;
+
+openForStatement
+    : OPEN (cursorVariable | hostCursorVariable) FOR (select | dynamicSqlStmt) 
plsqlUsingClause? SEMI_
+    ;
+
+cursorVariable
+    : variableName
+    ;
+
+plsqlUsingClause
+    : USING (IN | OUT | IN OUT)? bindArgument (COMMA_? (IN | OUT | IN OUT)? 
bindArgument)*
+    ;
+
+bindArgument
+    : expression
+    ;
+
+pipeRowStatement
+    : PIPE ROW LP_ row=expression RP_ SEMI_
+    ;
+
+plsqlBlock
+    : ((SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)*)? (DECLARE 
declareSection)? body
+    ;
+
+procedureCall
+    : (packageName DOT_)? procedureName (LP_ (parameter=expression (COMMA_ 
parameter=expression)*)? RP_)? SEMI_
+    ;
+
+raiseStatement
+    : RAISE name? SEMI_
+    ;
+
+returnStatement
+    : RETURN expression? SEMI_
+    ;
+
+selectIntoStatement
+    : SELECT (DISTINCT | UNIQUE | ALL)? selectList (selectIntoClause | 
bulkCollectIntoClause) FROM fromClauseList whereClause? 
hierarchicalQueryClause? groupByClause? modelClause? windowClause? 
orderByClause? rowLimitingClause? SEMI_
+    ;
+
+// TODO into_clause of PL/SQL
+selectIntoClause
+    : INTO (variableName (COMMA_ variableName)* | record)
+    ;
+
+record
+    : name
+    ;
+
+bulkCollectIntoClause
+    : BULK COLLECT INTO (collection=name | hostArray)
+    ;
+
+hostArray
+    : COLON_ variableName
+    ;
+
+hostCursorVariable
+    : COLON_ variableName
+    ;
+
+actualCursorParameter
+    : expression
+    ;
+
+sqlStatementInPlsql
+    : (commit
+    // TODO collection_method_call
+    | delete
+    | insert
+    | lockTable
+    | merge
+    | rollback
+    | savepoint
+    | setTransaction
+    | update
+    ) SEMI_
+    ;
+
+whileLoopStatement
+    : WHILE booleanExpression
+    LOOP statement+ END LOOP label? SEMI_
     ;
 
 exceptionHandler
@@ -276,7 +557,7 @@ rowtypeAttribute
 
 pragma
     : autonomousTransPragma | restrictReferencesPragma
-//    TODO Support more pragma
+    // TODO Support more pragma
     ;
 
 autonomousTransPragma
@@ -292,11 +573,11 @@ simpleDmlTrigger
     ;
 
 dmlEventClause
-    : dmlEventTrigger (OR dmlEventTrigger)* ON viewName
+    : dmlEventElement (OR dmlEventElement)* ON viewName
     ;
 
-dmlEventTrigger
-    : DELETE | INSERT | UPDATE (OF columnName (COMMA_ columnName)*)?
+dmlEventElement
+    : (DELETE | INSERT | UPDATE) (OF LP_ columnName (COMMA_ columnName)* RP_)?
     ;
 
 systemTrigger
diff --git a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4 
b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4
index 8388c081011..dd8b3bc4f42 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4
@@ -60,3 +60,5 @@ SEMI_:               ';';
 DOLLAR_:             '$';
 ASSIGNMENT_OPERATOR_:':=';
 ARROW_:              '=>';
+EXPONENT_:           '**';
+RANGE_OPERATOR_:     '..';
diff --git 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
index e13066d1237..4420a4e23ff 100644
--- 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
+++ 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
@@ -107,6 +107,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlTab
 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
 import 
org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.SequenceFunction;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexNameSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
@@ -117,26 +118,12 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.Column
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.datetime.DatetimeExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalDayToSecondExpression;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalYearToMonthExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.multiset.MultisetExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlElementFunctionSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespaceStringAsIdentifierSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespacesClauseSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlPiFunctionSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlQueryAndExistsFunctionSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlSerializeFunctionSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableColumnSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableFunctionSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableOptionsSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
@@ -156,6 +143,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegm
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParameterMarkerSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtils;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
@@ -167,13 +155,34 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.Number
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.OtherLiteralValue;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.datetime.DatetimeExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalDayToSecondExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalYearToMonthExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.multiset.MultisetExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlElementFunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespaceStringAsIdentifierSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespacesClauseSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlPiFunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlQueryAndExistsFunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlSerializeFunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableFunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableOptionsSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.OracleSelectStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.CursorForLoopStatementSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -186,6 +195,22 @@ public abstract class OracleStatementVisitor extends 
OracleStatementBaseVisitor<
     
     private final Collection<ParameterMarkerSegment> 
statementParameterMarkerSegments = new LinkedList<>();
     
+    private final List<SQLStatementSegment> sqlStatementsInPlsql = new 
ArrayList<>();
+    
+    private final List<ProcedureCallNameSegment> procedureCallNames = new 
ArrayList<>();
+    
+    private final List<ExpressionSegment> dynamicSqlStatementExpressions = new 
ArrayList<>();
+    
+    private final Collection<String> variableNames = new HashSet<>();
+    
+    private final Map<String, SQLStatement> cursorStatements = new HashMap<>();
+    
+    private final List<CursorForLoopStatementSegment> 
cursorForLoopStatementSegments = new ArrayList<>();
+    
+    private final Map<Integer, Set<SQLStatement>> tempCursorForLoopStatements 
= new HashMap<>();
+    
+    private int cursorForLoopLevel;
+    
     @Override
     public final ASTNode visitParameterMarker(final ParameterMarkerContext 
ctx) {
         return new ParameterMarkerValue(globalParameterMarkerSegments.size(), 
ParameterMarkerType.QUESTION);
@@ -306,6 +331,9 @@ public abstract class OracleStatementVisitor extends 
OracleStatementBaseVisitor<
     
     @Override
     public final ASTNode visitColumnName(final ColumnNameContext ctx) {
+        if (SequenceFunction.valueFrom(ctx.name().getText()).isPresent()) {
+            return createSequenceFunction(ctx);
+        }
         ColumnSegment result = new 
ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), 
(IdentifierValue) visit(ctx.name()));
         OwnerContext owner = ctx.owner();
         if (null != owner) {
@@ -317,6 +345,15 @@ public abstract class OracleStatementVisitor extends 
OracleStatementBaseVisitor<
         return result;
     }
     
+    private FunctionSegment createSequenceFunction(final ColumnNameContext 
ctx) {
+        FunctionSegment result = new 
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), 
ctx.name().getText(), getOriginalText(ctx));
+        OwnerContext owner = ctx.owner();
+        if (null != owner) {
+            result.setOwner(new OwnerSegment(owner.getStart().getStartIndex(), 
owner.getStop().getStopIndex(), (IdentifierValue) visit(owner.identifier())));
+        }
+        return result;
+    }
+    
     @Override
     public final ASTNode visitViewName(final ViewNameContext ctx) {
         SimpleTableSegment result = new SimpleTableSegment(new 
TableNameSegment(ctx.name().getStart().getStartIndex(),
@@ -1219,4 +1256,18 @@ public abstract class OracleStatementVisitor extends 
OracleStatementBaseVisitor<
         statementParameterMarkerSegments.clear();
         return result;
     }
+    
+    /**
+     * Increase cursor for loop level.
+     */
+    protected void increaseCursorForLoopLevel() {
+        ++cursorForLoopLevel;
+    }
+    
+    /**
+     * Decrease cursor for loop level.
+     */
+    protected void decreaseCursorForLoopLevel() {
+        --cursorForLoopLevel;
+    }
 }
diff --git 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
index cf7ab2bc570..3eb8230958f 100644
--- 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
+++ 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
@@ -53,6 +53,7 @@ public final class OracleDALStatementVisitor extends 
OracleStatementVisitor impl
             result.setStatement((SQLStatement) visitor.visit(ctx.select()));
         }
         result.addParameterMarkerSegments(ctx.getParent() instanceof 
ExecuteContext ? getGlobalParameterMarkerSegments() : 
popAllStatementParameterMarkerSegments());
+        result.getVariableNames().addAll(getVariableNames());
         return result;
     }
 }
diff --git 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
index 40319e4ccab..2577d9b45ed 100644
--- 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
+++ 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
@@ -64,6 +64,8 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Associ
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AuditContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AuditTraditionalContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AuditUnifiedContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.BodyContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CollectionVariableDeclContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnClausesContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnDefinitionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnNameContext;
@@ -92,8 +94,8 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Create
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreatePFileContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateProcedureContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateProfileContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRestorePointContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRelationalTableClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRestorePointContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRollbackSegmentContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateSPFileContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateSequenceContext;
@@ -103,8 +105,11 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Create
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateTriggerContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateTypeContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateViewContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CursorDefinitionContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CursorForLoopStatementContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DataTypeDefinitionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DisassociateStatisticsContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DmlStatementContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropClusterContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropColumnClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropColumnSpecificationContext;
@@ -141,15 +146,17 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropTa
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropTriggerContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropTypeContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropViewContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DynamicSqlStmtContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ExceptionHandlerContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FlashbackDatabaseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FlashbackTableContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FunctionContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SwitchContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexExpressionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexExpressionsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexTypeNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InlineConstraintContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ItemDeclarationContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModifyColPropertiesContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModifyCollectionRetrievalContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModifyColumnSpecificationContext;
@@ -159,20 +166,34 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.NoAudi
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ObjectBaseTypeDefContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ObjectSubTypeDefContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ObjectTypeDefContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OpenForStatementContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OperateColumnClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OutOfLineConstraintContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OutOfLineRefConstraintContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OwnerContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PackageNameContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ParameterDeclarationContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PlsqlBlockContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PlsqlFunctionSourceContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PlsqlProcedureSourceContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ProcedureCallContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PurgeContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RelationalPropertyContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RenameContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SchemaNameContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectIntoStatementContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SqlStatementInPlsqlContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.StatementContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SwitchContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SystemActionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TruncateTableContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TypeNameContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.VariableNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.VarrayTypeSpecContext;
 import 
org.apache.shardingsphere.sql.parser.oracle.visitor.statement.OracleStatementVisitor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.AlterDefinitionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.CreateDefinitionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.column.ColumnDefinitionSegment;
@@ -188,16 +209,21 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.al
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexTypeSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.packages.PackageSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.routine.FunctionNameSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.tablespace.TablespaceSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.type.TypeDefinitionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.type.TypeSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+import 
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleAlterAnalyticViewStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleAlterAttributeDimensionStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleAlterAuditPolicyStatement;
@@ -316,10 +342,18 @@ import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.Ora
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleSwitchStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleSystemActionStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleTruncateStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.OracleSelectStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.CursorForLoopStatementSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
+import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -1032,7 +1066,34 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
     
     @Override
     public ASTNode visitCreateFunction(final CreateFunctionContext ctx) {
-        return new OracleCreateFunctionStatement();
+        return visitCreateFunction0(ctx);
+    }
+    
+    private ASTNode visitCreateFunction0(final CreateFunctionContext ctx) {
+        if (null != ctx.plsqlFunctionSource().declareSection()) {
+            visit(ctx.plsqlFunctionSource().declareSection());
+        }
+        if (null != ctx.plsqlFunctionSource().body()) {
+            visit(ctx.plsqlFunctionSource().body());
+        }
+        
getSqlStatementsInPlsql().sort(Comparator.comparingInt(SQLStatementSegment::getStartIndex));
+        
getProcedureCallNames().sort(Comparator.comparingInt(ProcedureCallNameSegment::getStartIndex));
+        
getDynamicSqlStatementExpressions().sort(Comparator.comparingInt(ExpressionSegment::getStartIndex));
+        OracleCreateFunctionStatement result = new 
OracleCreateFunctionStatement(getSqlStatementsInPlsql(), 
getProcedureCallNames(), getDynamicSqlStatementExpressions());
+        result.setFunctionName(visitFunctionName(ctx.plsqlFunctionSource()));
+        return result;
+    }
+    
+    private FunctionNameSegment visitFunctionName(final 
PlsqlFunctionSourceContext ctx) {
+        OwnerContext schema = ctx.function().owner();
+        IdentifierValue functionName = (IdentifierValue) 
visit(ctx.function().name().identifier());
+        if (null == schema) {
+            return new 
FunctionNameSegment(ctx.function().name().start.getStartIndex(), 
ctx.function().name().stop.getStopIndex(), functionName);
+        }
+        OwnerSegment owner = new OwnerSegment(schema.start.getStartIndex(), 
schema.stop.getStopIndex(), (IdentifierValue) visit(schema.identifier()));
+        FunctionNameSegment result = new 
FunctionNameSegment(ctx.function().start.getStartIndex(), 
ctx.function().stop.getStopIndex(), functionName);
+        result.setOwner(owner);
+        return result;
     }
     
     @Override
@@ -1264,7 +1325,311 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
     
     @Override
     public ASTNode visitCreateProcedure(final CreateProcedureContext ctx) {
-        return new OracleCreateProcedureStatement();
+        return visitCreateProcedure0(ctx);
+    }
+    
+    private ASTNode visitCreateProcedure0(final CreateProcedureContext ctx) {
+        if (null != ctx.plsqlProcedureSource().parameterDeclaration()) {
+            for (ParameterDeclarationContext each : 
ctx.plsqlProcedureSource().parameterDeclaration()) {
+                visit(each);
+            }
+        }
+        if (null != ctx.plsqlProcedureSource().declareSection()) {
+            visit(ctx.plsqlProcedureSource().declareSection());
+        }
+        if (null != ctx.plsqlProcedureSource().body()) {
+            visit(ctx.plsqlProcedureSource().body());
+        }
+        
getSqlStatementsInPlsql().sort(Comparator.comparingInt(SQLStatementSegment::getStartIndex));
+        
getProcedureCallNames().sort(Comparator.comparingInt(ProcedureCallNameSegment::getStartIndex));
+        
getDynamicSqlStatementExpressions().sort(Comparator.comparingInt(ExpressionSegment::getStartIndex));
+        OracleCreateProcedureStatement result = new 
OracleCreateProcedureStatement(getSqlStatementsInPlsql(), 
getProcedureCallNames(), getDynamicSqlStatementExpressions());
+        
result.setProcedureName(visitProcedureName(ctx.plsqlProcedureSource()));
+        result.getVariableNames().addAll(getVariableNames());
+        getSqlStatementsInPlsql().forEach(each -> 
each.getSqlStatement().getVariableNames().addAll(getVariableNames()));
+        
result.getCursorForLoopStatements().addAll(getCursorForLoopStatementSegments());
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitParameterDeclaration(final ParameterDeclarationContext 
ctx) {
+        if (null != ctx.parameterName()) {
+            IdentifierValue paramName = (IdentifierValue) 
visit(ctx.parameterName().identifier());
+            getVariableNames().add(paramName.getValue().toLowerCase());
+            return new VariableSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), paramName.getValue());
+        }
+        return super.visitParameterDeclaration(ctx);
+    }
+    
+    @Override
+    public ASTNode visitItemDeclaration(final ItemDeclarationContext ctx) {
+        CollectionValue<VariableSegment> result = new CollectionValue<>();
+        if (null != ctx.collectionVariableDecl() && null != 
ctx.collectionVariableDecl().variableName()) {
+            for (VariableNameContext each : 
ctx.collectionVariableDecl().variableName()) {
+                getVariableSegment(each).ifPresent(optional -> 
result.getValue().add(optional));
+            }
+        }
+        if (null != ctx.constantDeclaration() && null != 
ctx.constantDeclaration().variableName()) {
+            
getVariableSegment(ctx.constantDeclaration().variableName()).ifPresent(optional 
-> result.getValue().add(optional));
+        }
+        if (null != ctx.cursorVariableDeclaration() && null != 
ctx.cursorVariableDeclaration().variableName()) {
+            
getVariableSegment(ctx.cursorVariableDeclaration().variableName()).ifPresent(optional
 -> result.getValue().add(optional));
+        }
+        if (null != ctx.exceptionDeclaration() && null != 
ctx.exceptionDeclaration().variableName()) {
+            
getVariableSegment(ctx.exceptionDeclaration().variableName()).ifPresent(optional
 -> result.getValue().add(optional));
+        }
+        if (null != ctx.recordVariableDeclaration() && null != 
ctx.recordVariableDeclaration().variableName()) {
+            
getVariableSegment(ctx.recordVariableDeclaration().variableName()).ifPresent(optional
 -> result.getValue().add(optional));
+        }
+        if (null != ctx.variableDeclaration() && null != 
ctx.variableDeclaration().variableName()) {
+            
getVariableSegment(ctx.variableDeclaration().variableName()).ifPresent(optional 
-> result.getValue().add(optional));
+        }
+        return result;
+    }
+    
+    private Optional<VariableSegment> getVariableSegment(final 
VariableNameContext variableNameContext) {
+        if (null == variableNameContext) {
+            return Optional.empty();
+        }
+        if (null != variableNameContext.identifier()) {
+            String variableName = ((IdentifierValue) 
visitIdentifier(variableNameContext.identifier())).getValue().toLowerCase();
+            getVariableNames().add(variableName);
+            return Optional.of(new 
VariableSegment(variableNameContext.start.getStartIndex(), 
variableNameContext.stop.getStopIndex(), variableName));
+        }
+        if (null != variableNameContext.stringLiterals()) {
+            String variableName = 
variableNameContext.stringLiterals().STRING_().getText().toLowerCase();
+            getVariableNames().add(variableName);
+            return Optional.of(new 
VariableSegment(variableNameContext.start.getStartIndex(), 
variableNameContext.stop.getStopIndex(), variableName));
+        }
+        return Optional.empty();
+    }
+    
+    @Override
+    public ASTNode visitCollectionVariableDecl(final 
CollectionVariableDeclContext ctx) {
+        CollectionValue<VariableSegment> result = new CollectionValue<>();
+        if (null == ctx.variableName()) {
+            return super.visitCollectionVariableDecl(ctx);
+        }
+        for (VariableNameContext each : ctx.variableName()) {
+            getVariableSegment(each).ifPresent(optional -> 
result.getValue().add(optional));
+        }
+        return result;
+    }
+    
+    private FunctionNameSegment visitProcedureName(final 
PlsqlProcedureSourceContext ctx) {
+        SchemaNameContext schemaName = ctx.schemaName();
+        IdentifierValue procedureName = (IdentifierValue) 
visit(ctx.procedureName().identifier());
+        if (null == schemaName) {
+            return new 
FunctionNameSegment(ctx.procedureName().start.getStartIndex(), 
ctx.procedureName().stop.getStopIndex(), procedureName);
+        }
+        OwnerSegment owner = new 
OwnerSegment(schemaName.start.getStartIndex(), schemaName.stop.getStopIndex(), 
(IdentifierValue) visit(schemaName.identifier()));
+        FunctionNameSegment result = new 
FunctionNameSegment(schemaName.start.getStartIndex(), 
ctx.procedureName().stop.getStopIndex(), procedureName);
+        result.setOwner(owner);
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitCursorDefinition(final CursorDefinitionContext ctx) {
+        SQLStatement statement = visitSelect0(ctx.select());
+        getCursorStatements().put(null != ctx.variableName().identifier() ? 
new IdentifierValue(ctx.variableName().getText()).getValue()
+                : new 
StringLiteralValue(ctx.variableName().getText()).getValue(), statement);
+        return defaultResult();
+    }
+    
+    @Override
+    public ASTNode visitBody(final BodyContext ctx) {
+        for (StatementContext each : ctx.statement()) {
+            visit(each);
+        }
+        for (ExceptionHandlerContext eachExceptionHandler : 
ctx.exceptionHandler()) {
+            for (StatementContext each : eachExceptionHandler.statement()) {
+                visit(each);
+            }
+        }
+        return defaultResult();
+    }
+    
+    @Override
+    public ASTNode visitProcedureCall(final ProcedureCallContext ctx) {
+        int startIndex = ctx.procedureName().start.getStartIndex();
+        PackageSegment packageSegment = null;
+        if (null != ctx.packageName()) {
+            startIndex = ctx.packageName().start.getStartIndex();
+            packageSegment = (PackageSegment) visit(ctx.packageName());
+        }
+        ProcedureCallNameSegment result = new 
ProcedureCallNameSegment(startIndex, ctx.procedureName().stop.getStopIndex(), 
(IdentifierValue) visit(ctx.procedureName().identifier()));
+        result.setPackageSegment(packageSegment);
+        getProcedureCallNames().add(result);
+        return defaultResult();
+    }
+    
+    @Override
+    public ASTNode visitCursorForLoopStatement(final 
CursorForLoopStatementContext ctx) {
+        SQLStatement relatedCursorStatement;
+        String cursorName = null;
+        if (null != ctx.select()) {
+            relatedCursorStatement = visitSelect0(ctx.select());
+        } else {
+            cursorName = null == ctx.cursor().variableName().identifier()
+                    ? new StringLiteralValue(ctx.cursor().getText()).getValue()
+                    : new IdentifierValue(ctx.cursor().getText()).getValue();
+            relatedCursorStatement = getCursorStatements().get(cursorName);
+        }
+        increaseCursorForLoopLevel();
+        for (StatementContext each : ctx.statement()) {
+            visit(each);
+        }
+        Set<SQLStatement> sqlStatements = 
getTempCursorForLoopStatements().remove(getCursorForLoopLevel());
+        CursorForLoopStatementSegment cursorForLoopStatementSegment = new 
CursorForLoopStatementSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(),
+                new IdentifierValue(ctx.record().getText()).getValue(), 
cursorName, relatedCursorStatement, null == sqlStatements ? 
Collections.emptyList() : sqlStatements);
+        getCursorForLoopStatementSegments().add(cursorForLoopStatementSegment);
+        decreaseCursorForLoopLevel();
+        return defaultResult();
+    }
+    
+    @Override
+    public ASTNode visitOpenForStatement(final OpenForStatementContext ctx) {
+        if (null != ctx.select()) {
+            visitSelect0(ctx.select());
+        }
+        // TODO handle SQL in dynamicString
+        return defaultResult();
+    }
+    
+    private SQLStatement visitSelect0(final SelectContext select) {
+        OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+        SQLStatement result = (SQLStatement) visitor.visitSelect(select);
+        getSqlStatementsInPlsql().add(new 
SQLStatementSegment(select.start.getStartIndex(), select.stop.getStopIndex(), 
result));
+        addToTempCursorForLoopStatements(result);
+        return result;
+    }
+    
+    private void addToTempCursorForLoopStatements(final SQLStatement 
sqlStatement) {
+        if (0 == getCursorForLoopLevel()) {
+            return;
+        }
+        for (int i = 1; i <= getCursorForLoopLevel(); i++) {
+            getTempCursorForLoopStatements().computeIfAbsent(i, key -> new 
LinkedHashSet<>()).add(sqlStatement);
+        }
+    }
+    
+    @Override
+    public ASTNode visitSqlStatementInPlsql(final SqlStatementInPlsqlContext 
ctx) {
+        if (null != ctx.commit()) {
+            OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitCommit(ctx.commit());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.commit().start.getStartIndex(), 
ctx.commit().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        // TODO visit collection_method_call
+        if (null != ctx.delete()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitDelete(ctx.delete());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.delete().start.getStartIndex(), 
ctx.delete().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.insert()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitInsert(ctx.insert());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.insert().start.getStartIndex(), 
ctx.insert().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.lockTable()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitLockTable(ctx.lockTable());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.lockTable().start.getStartIndex(), 
ctx.lockTable().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.merge()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitMerge(ctx.merge());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.merge().start.getStartIndex(), 
ctx.merge().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.rollback()) {
+            OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitRollback(ctx.rollback());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.rollback().start.getStartIndex(), 
ctx.rollback().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.savepoint()) {
+            OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitSavepoint(ctx.savepoint());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.savepoint().start.getStartIndex(), 
ctx.savepoint().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.setTransaction()) {
+            OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitSetTransaction(ctx.setTransaction());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.setTransaction().start.getStartIndex(), 
ctx.setTransaction().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.update()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitUpdate(ctx.update());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.update().start.getStartIndex(), 
ctx.update().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        return defaultResult();
+    }
+    
+    private OracleStatementVisitor createOracleTCLStatementVisitor() {
+        OracleStatementVisitor result = new OracleTCLStatementVisitor();
+        result.getVariableNames().addAll(getVariableNames());
+        return result;
+    }
+    
+    private OracleStatementVisitor createOracleDMLStatementVisitor() {
+        OracleStatementVisitor result = new OracleDMLStatementVisitor();
+        result.getVariableNames().addAll(getVariableNames());
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitDmlStatement(final DmlStatementContext ctx) {
+        if (null != ctx.insert()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitInsert(ctx.insert());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.insert().start.getStartIndex(), 
ctx.insert().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.update()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitUpdate(ctx.update());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.update().start.getStartIndex(), 
ctx.update().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.delete()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitDelete(ctx.delete());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.delete().start.getStartIndex(), 
ctx.delete().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        if (null != ctx.merge()) {
+            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            SQLStatement result = (SQLStatement) 
visitor.visitMerge(ctx.merge());
+            getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.merge().start.getStartIndex(), 
ctx.merge().stop.getStopIndex(), result));
+            addToTempCursorForLoopStatements(result);
+        }
+        // TODO Handling dynamicSqlStmt if we can
+        return defaultResult();
+    }
+    
+    @Override
+    public ASTNode visitSelectIntoStatement(final SelectIntoStatementContext 
ctx) {
+        // TODO Visit intoClause
+        OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+        OracleSelectStatement result = (OracleSelectStatement) 
visitor.visitSelectIntoStatement(ctx);
+        getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
result));
+        addToTempCursorForLoopStatements(result);
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitDynamicSqlStmt(final DynamicSqlStmtContext ctx) {
+        ExpressionSegment result = (ExpressionSegment) 
visit(ctx.expression().expr());
+        getDynamicSqlStatementExpressions().add(result);
+        return result;
     }
     
     @Override
diff --git 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
index 3d75b33cce8..989384bd03b 100644
--- 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
+++ 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
@@ -84,6 +84,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Refere
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RollupCubeClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectFromClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectIntoStatementContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectJoinOptionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectJoinSpecificationContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectListContext;
@@ -153,6 +154,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvai
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ModelSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParameterMarkerSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.PivotSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.CollectionTableSegment;
@@ -191,6 +193,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.Ora
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -212,6 +215,7 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
             result.setWhere((WhereSegment) visit(ctx.whereClause()));
         }
         result.addParameterMarkerSegments(ctx.getParent() instanceof 
ExecuteContext ? getGlobalParameterMarkerSegments() : 
popAllStatementParameterMarkerSegments());
+        result.getVariableNames().addAll(getVariableNames());
         return result;
     }
     
@@ -319,6 +323,7 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
                     getOriginalText(ctx.selectSubquery()));
             result.setInsertSelect(subquerySegment);
         }
+        result.getVariableNames().addAll(getVariableNames());
         return result;
     }
     
@@ -343,17 +348,29 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         }
         result.setInsertSelect(new 
SubquerySegment(ctx.selectSubquery().start.getStartIndex(), 
ctx.selectSubquery().stop.getStopIndex(), (OracleSelectStatement) 
visit(ctx.selectSubquery()),
                 getOriginalText(ctx.selectSubquery())));
+        result.getVariableNames().addAll(getVariableNames());
         return result;
     }
     
     private Collection<InsertStatement> createInsertIntoSegments(final 
List<MultiTableElementContext> ctx) {
         Collection<InsertStatement> result = new LinkedList<>();
+        Collection<ParameterMarkerSegment> addedSegments = new HashSet<>();
         for (MultiTableElementContext each : ctx) {
-            result.add((OracleInsertStatement) visit(each));
+            OracleInsertStatement oracleInsertStatement = 
(OracleInsertStatement) visit(each);
+            addParameterMarkerSegments(addedSegments, oracleInsertStatement);
+            result.add(oracleInsertStatement);
         }
         return result;
     }
     
+    private void addParameterMarkerSegments(final 
Collection<ParameterMarkerSegment> addedSegments, final OracleInsertStatement 
oracleInsertStatement) {
+        for (ParameterMarkerSegment parameterMarkerSegment : 
popAllStatementParameterMarkerSegments()) {
+            if (addedSegments.add(parameterMarkerSegment)) {
+                
oracleInsertStatement.addParameterMarkerSegments(Collections.singletonList(parameterMarkerSegment));
+            }
+        }
+    }
+    
     @Override
     public ASTNode visitInsertValuesClause(final InsertValuesClauseContext 
ctx) {
         OracleInsertStatement result = new OracleInsertStatement();
@@ -393,6 +410,7 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
             result.setWhere((WhereSegment) visit(ctx.whereClause()));
         }
         result.addParameterMarkerSegments(ctx.getParent() instanceof 
ExecuteContext ? getGlobalParameterMarkerSegments() : 
popAllStatementParameterMarkerSegments());
+        result.getVariableNames().addAll(getVariableNames());
         return result;
     }
     
@@ -409,6 +427,32 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         return new SubqueryTableSegment(subquerySegment);
     }
     
+    @Override
+    public OracleSelectStatement visitSelectIntoStatement(final 
SelectIntoStatementContext ctx) {
+        OracleSelectStatement result = new OracleSelectStatement();
+        result.setProjections((ProjectionsSegment) visit(ctx.selectList()));
+        // TODO Visit selectIntoClause, bulkCollectIntoClause
+        result.setFrom((TableSegment) visit(ctx.fromClauseList()));
+        if (null != ctx.whereClause()) {
+            result.setWhere((WhereSegment) visit(ctx.whereClause()));
+        }
+        if (null != ctx.groupByClause()) {
+            result.setGroupBy((GroupBySegment) visit(ctx.groupByClause()));
+        }
+        // TODO Visit hierarchicalQueryClause
+        if (null != ctx.modelClause()) {
+            result.setModelSegment((ModelSegment) visit(ctx.modelClause()));
+        }
+        // TODO Visit windowClause
+        if (null != ctx.orderByClause()) {
+            result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
+        }
+        // TODO Visit rowLimitingClause
+        result.addParameterMarkerSegments(ctx.getParent() instanceof 
ExecuteContext ? getGlobalParameterMarkerSegments() : 
popAllStatementParameterMarkerSegments());
+        result.getVariableNames().addAll(getVariableNames());
+        return result;
+    }
+    
     @Override
     public ASTNode visitMultiTableElement(final MultiTableElementContext ctx) {
         OracleInsertStatement result = (OracleInsertStatement) 
visit(ctx.insertIntoClause());
@@ -423,6 +467,7 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
     public ASTNode visitSelect(final SelectContext ctx) {
         OracleSelectStatement result = (OracleSelectStatement) 
visit(ctx.selectSubquery());
         result.addParameterMarkerSegments(ctx.getParent() instanceof 
ExecuteContext ? getGlobalParameterMarkerSegments() : 
popAllStatementParameterMarkerSegments());
+        result.getVariableNames().addAll(getVariableNames());
         if (null != ctx.forUpdateClause()) {
             result.setLock((LockSegment) visit(ctx.forUpdateClause()));
         }
@@ -555,6 +600,7 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
             result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
         }
         result.addParameterMarkerSegments(ctx.getParent() instanceof 
ExecuteContext ? getGlobalParameterMarkerSegments() : 
popAllStatementParameterMarkerSegments());
+        result.getVariableNames().addAll(getVariableNames());
         return result;
     }
     
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SequenceFunction.java
similarity index 51%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
copy to 
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SequenceFunction.java
index 2cf7e238fac..d8d390994eb 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SequenceFunction.java
@@ -15,12 +15,34 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package org.apache.shardingsphere.sql.parser.sql.common.enums;
 
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import com.cedarsoftware.util.CaseInsensitiveMap;
+
+import java.util.Map;
+import java.util.Optional;
 
 /**
- * Create function statement test case.
+ * Sequence function.
  */
-public final class CreateFunctionStatementTestCase extends SQLParserTestCase {
+public enum SequenceFunction {
+    
+    CURRVAL, NEXTVAL;
+    
+    private static final Map<String, SequenceFunction> SEQUENCE_FUNCTIONS = 
new CaseInsensitiveMap<>(2, 1F);
+    
+    static {
+        SEQUENCE_FUNCTIONS.put("CURRVAL", CURRVAL);
+        SEQUENCE_FUNCTIONS.put("NEXTVAL", NEXTVAL);
+    }
+    
+    /**
+     * Get sequence function value from text.
+     *
+     * @param text text
+     * @return sequence function value
+     */
+    public static Optional<SequenceFunction> valueFrom(final String text) {
+        return Optional.ofNullable(SEQUENCE_FUNCTIONS.get(text));
+    }
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
index c3c6f68f665..20efbccffcc 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
@@ -24,9 +24,27 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenE
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.DatetimeProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.IntervalExpressionProjection;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.GroupBySegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ExpressionOrderByItemSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.HavingSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.CollectionTableSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
 
 import java.util.Collection;
 import java.util.LinkedList;
@@ -87,4 +105,123 @@ public final class ColumnExtractor {
             columnSegments.addAll(ColumnExtractor.extract(each));
         }
     }
+    
+    /**
+     * Extract column segments.
+     *
+     * @param columnSegments column segments
+     * @param statement select statement
+     * @param containsSubQuery whether contains sub query
+     */
+    public static void extractFromSelectStatement(final 
Collection<ColumnSegment> columnSegments, final SelectStatement statement, 
final boolean containsSubQuery) {
+        extractFromProjections(columnSegments, 
statement.getProjections().getProjections(), containsSubQuery);
+        extractFromSelectStatementWithoutProjection(columnSegments, statement, 
containsSubQuery);
+    }
+    
+    /**
+     * Extract from select statement without projection.
+     *
+     * @param columnSegments column segments
+     * @param statement select statement
+     * @param containsSubQuery whether contains sub query
+     */
+    public static void extractFromSelectStatementWithoutProjection(final 
Collection<ColumnSegment> columnSegments, final SelectStatement statement, 
final boolean containsSubQuery) {
+        extractFromTable(columnSegments, statement.getFrom(), 
containsSubQuery);
+        statement.getWhere().ifPresent(optional -> 
extractFromWhere(columnSegments, optional, containsSubQuery));
+        statement.getGroupBy().ifPresent(optional -> 
extractFromGroupBy(columnSegments, optional, containsSubQuery));
+        statement.getHaving().ifPresent(optional -> 
extractFromHaving(columnSegments, optional, containsSubQuery));
+        statement.getOrderBy().ifPresent(optional -> 
extractFromOrderBy(columnSegments, optional, containsSubQuery));
+        statement.getCombine().ifPresent(optional -> 
extractFromSelectStatement(columnSegments, optional.getRight(), 
containsSubQuery));
+    }
+    
+    /**
+     * Extract column segments.
+     *
+     * @param columnSegments column segments
+     * @param projections projection segments
+     * @param containsSubQuery contains sub query
+     */
+    public static void extractFromProjections(final Collection<ColumnSegment> 
columnSegments, final Collection<ProjectionSegment> projections, final boolean 
containsSubQuery) {
+        for (ProjectionSegment each : projections) {
+            if (each instanceof ColumnProjectionSegment) {
+                columnSegments.add(((ColumnProjectionSegment) 
each).getColumn());
+            }
+            if (each instanceof AggregationProjectionSegment) {
+                for (ExpressionSegment parameter : 
((AggregationProjectionSegment) each).getParameters()) {
+                    
columnSegments.addAll(ExpressionExtractUtils.extractColumns(parameter, 
containsSubQuery));
+                }
+            }
+            if (each instanceof DatetimeProjectionSegment) {
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((DatetimeProjectionSegment)
 each).getLeft(), containsSubQuery));
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((DatetimeProjectionSegment)
 each).getRight(), containsSubQuery));
+            }
+            if (each instanceof ExpressionProjectionSegment) {
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((ExpressionProjectionSegment)
 each).getExpr(), containsSubQuery));
+            }
+            if (each instanceof IntervalExpressionProjection) {
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((IntervalExpressionProjection)
 each).getLeft(), containsSubQuery));
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((IntervalExpressionProjection)
 each).getRight(), containsSubQuery));
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((IntervalExpressionProjection)
 each).getMinus(), containsSubQuery));
+            }
+            if (each instanceof SubqueryProjectionSegment && containsSubQuery) 
{
+                extractFromSelectStatement(columnSegments, 
((SubqueryProjectionSegment) each).getSubquery().getSelect(), true);
+            }
+        }
+    }
+    
+    private static void extractFromTable(final Collection<ColumnSegment> 
columnSegments, final TableSegment tableSegment, final boolean 
containsSubQuery) {
+        if (null == tableSegment) {
+            return;
+        }
+        if (tableSegment instanceof CollectionTableSegment) {
+            
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((CollectionTableSegment)
 tableSegment).getExpressionSegment(), containsSubQuery));
+        }
+        if (tableSegment instanceof JoinTableSegment) {
+            extractFromTable(columnSegments, ((JoinTableSegment) 
tableSegment).getLeft(), containsSubQuery);
+            extractFromTable(columnSegments, ((JoinTableSegment) 
tableSegment).getRight(), containsSubQuery);
+            
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((JoinTableSegment) 
tableSegment).getCondition(), containsSubQuery));
+            columnSegments.addAll(((JoinTableSegment) 
tableSegment).getUsing());
+            columnSegments.addAll(((JoinTableSegment) 
tableSegment).getDerivedUsing());
+        }
+        if (tableSegment instanceof SubqueryTableSegment && containsSubQuery) {
+            extractFromSelectStatement(columnSegments, ((SubqueryTableSegment) 
tableSegment).getSubquery().getSelect(), true);
+        }
+    }
+    
+    /**
+     * Extract column segments.
+     *
+     * @param columnSegments column segments
+     * @param whereSegment where segment
+     * @param containsSubQuery contains sub query
+     */
+    public static void extractFromWhere(final Collection<ColumnSegment> 
columnSegments, final WhereSegment whereSegment, final boolean 
containsSubQuery) {
+        
columnSegments.addAll(ExpressionExtractUtils.extractColumns(whereSegment.getExpr(),
 containsSubQuery));
+    }
+    
+    private static void extractFromGroupBy(final Collection<ColumnSegment> 
columnSegments, final GroupBySegment groupBySegment, final boolean 
containsSubQuery) {
+        for (OrderByItemSegment each : groupBySegment.getGroupByItems()) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                columnSegments.add(((ColumnOrderByItemSegment) 
each).getColumn());
+            }
+            if (each instanceof ExpressionOrderByItemSegment) {
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((ExpressionOrderByItemSegment)
 each).getExpr(), containsSubQuery));
+            }
+        }
+    }
+    
+    private static void extractFromHaving(final Collection<ColumnSegment> 
columnSegments, final HavingSegment havingSegment, final boolean 
containsSubQuery) {
+        
columnSegments.addAll(ExpressionExtractUtils.extractColumns(havingSegment.getExpr(),
 containsSubQuery));
+    }
+    
+    private static void extractFromOrderBy(final Collection<ColumnSegment> 
columnSegments, final OrderBySegment orderBySegment, final boolean 
containsSubQuery) {
+        for (OrderByItemSegment each : orderBySegment.getOrderByItems()) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                columnSegments.add(((ColumnOrderByItemSegment) 
each).getColumn());
+            }
+            if (each instanceof ExpressionOrderByItemSegment) {
+                
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((ExpressionOrderByItemSegment)
 each).getExpr(), containsSubQuery));
+            }
+        }
+    }
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
index 6d69c31ae75..1ba74ee51d9 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
@@ -20,15 +20,31 @@ package 
org.apache.shardingsphere.sql.parser.sql.common.util;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.LogicalOperator;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.TypeCastExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ValuesExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonTableExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.IntervalExpressionProjection;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.mysql.match.MatchAgainstExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.datetime.DatetimeExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.multiset.MultisetExpression;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -138,4 +154,93 @@ public final class ExpressionExtractUtils {
             }
         }
     }
+    
+    /**
+     * Extract columns.
+     *
+     * @param expression expression
+     * @param containsSubQuery contains sub query or not
+     * @return columns
+     */
+    public static Collection<ColumnSegment> extractColumns(final 
ExpressionSegment expression, final boolean containsSubQuery) {
+        if (expression instanceof ColumnSegment) {
+            return Collections.singletonList((ColumnSegment) expression);
+        }
+        Collection<ColumnSegment> result = new LinkedList<>();
+        if (expression instanceof AggregationProjectionSegment) {
+            for (ExpressionSegment each : ((AggregationProjectionSegment) 
expression).getParameters()) {
+                result.addAll(extractColumns(each, containsSubQuery));
+            }
+        }
+        if (expression instanceof BetweenExpression) {
+            result.addAll(extractColumns(((BetweenExpression) 
expression).getLeft(), containsSubQuery));
+            result.addAll(extractColumns(((BetweenExpression) 
expression).getBetweenExpr(), containsSubQuery));
+            result.addAll(extractColumns(((BetweenExpression) 
expression).getAndExpr(), containsSubQuery));
+        }
+        if (expression instanceof BinaryOperationExpression) {
+            result.addAll(extractColumns(((BinaryOperationExpression) 
expression).getLeft(), containsSubQuery));
+            result.addAll(extractColumns(((BinaryOperationExpression) 
expression).getRight(), containsSubQuery));
+        }
+        if (expression instanceof CaseWhenExpression) {
+            result.addAll(extractColumns(((CaseWhenExpression) 
expression).getCaseExpr(), containsSubQuery));
+            result.addAll(extractColumns(((CaseWhenExpression) 
expression).getElseExpr(), containsSubQuery));
+            ((CaseWhenExpression) expression).getWhenExprs().forEach(each -> 
result.addAll(extractColumns(each, containsSubQuery)));
+            ((CaseWhenExpression) expression).getThenExprs().forEach(each -> 
result.addAll(extractColumns(each, containsSubQuery)));
+        }
+        if (expression instanceof OuterJoinExpression) {
+            result.add(((OuterJoinExpression) expression).getColumnName());
+        }
+        if (expression instanceof CommonTableExpressionSegment) {
+            result.addAll(((CommonTableExpressionSegment) 
expression).getColumns());
+        }
+        if (expression instanceof DatetimeExpression) {
+            result.addAll(extractColumns(((DatetimeExpression) 
expression).getLeft(), containsSubQuery));
+            result.addAll(extractColumns(((DatetimeExpression) 
expression).getRight(), containsSubQuery));
+        }
+        if (expression instanceof ExpressionProjectionSegment) {
+            result.addAll(extractColumns(((ExpressionProjectionSegment) 
expression).getExpr(), containsSubQuery));
+        }
+        if (expression instanceof FunctionSegment) {
+            for (ExpressionSegment each : ((FunctionSegment) 
expression).getParameters()) {
+                result.addAll(extractColumns(each, containsSubQuery));
+            }
+        }
+        if (expression instanceof InExpression) {
+            result.addAll(extractColumns(((InExpression) 
expression).getLeft(), containsSubQuery));
+            result.addAll(extractColumns(((InExpression) 
expression).getRight(), containsSubQuery));
+        }
+        if (expression instanceof IntervalExpressionProjection) {
+            result.addAll(extractColumns(((IntervalExpressionProjection) 
expression).getLeft(), containsSubQuery));
+            result.addAll(extractColumns(((IntervalExpressionProjection) 
expression).getRight(), containsSubQuery));
+            result.addAll(extractColumns(((IntervalExpressionProjection) 
expression).getMinus(), containsSubQuery));
+        }
+        if (expression instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) 
expression).getItems()) {
+                result.addAll(extractColumns(each, containsSubQuery));
+            }
+        }
+        if (expression instanceof MatchAgainstExpression) {
+            result.add(((MatchAgainstExpression) expression).getColumnName());
+            result.addAll(extractColumns(((MatchAgainstExpression) 
expression).getExpr(), containsSubQuery));
+        }
+        if (expression instanceof MultisetExpression) {
+            result.addAll(extractColumns(((MultisetExpression) 
expression).getLeft(), containsSubQuery));
+            result.addAll(extractColumns(((MultisetExpression) 
expression).getRight(), containsSubQuery));
+        }
+        if (expression instanceof NotExpression) {
+            result.addAll(extractColumns(((NotExpression) 
expression).getExpression(), containsSubQuery));
+        }
+        if (expression instanceof ValuesExpression) {
+            for (InsertValuesSegment each : ((ValuesExpression) 
expression).getRowConstructorList()) {
+                each.getValues().forEach(value -> 
result.addAll(extractColumns(value, containsSubQuery)));
+            }
+        }
+        if (expression instanceof SubquerySegment && containsSubQuery) {
+            ColumnExtractor.extractFromSelectStatement(result, 
((SubquerySegment) expression).getSelect(), true);
+        }
+        if (expression instanceof SubqueryExpressionSegment && 
containsSubQuery) {
+            ColumnExtractor.extractFromSelectStatement(result, 
((SubqueryExpressionSegment) expression).getSubquery().getSelect(), true);
+        }
+        return result;
+    }
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
index 964dab98f2d..9ff381a3d46 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
@@ -77,4 +77,18 @@ public final class WhereExtractUtils {
         }
         return result;
     }
+    
+    /**
+     * Get subquery where segment without join conditions from SelectStatement.
+     *
+     * @param selectStatement SelectStatement
+     * @return subquery where segment collection
+     */
+    public static Collection<WhereSegment> 
getSubqueryWhereSegmentsWithoutJoinConditions(final SelectStatement 
selectStatement) {
+        Collection<WhereSegment> result = new LinkedList<>();
+        for (SubquerySegment each : 
SubqueryExtractUtils.getSubquerySegments(selectStatement)) {
+            each.getSelect().getWhere().ifPresent(result::add);
+        }
+        return result;
+    }
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
index 83c66294cf9..797412d2711 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
@@ -17,11 +17,26 @@
 
 package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
 
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateFunctionStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
+
+import java.util.List;
 
 /**
  * Oracle create function statement.
  */
+@RequiredArgsConstructor
+@Getter
 public final class OracleCreateFunctionStatement extends 
CreateFunctionStatement implements OracleStatement {
+    
+    private final List<SQLStatementSegment> sqlStatements;
+    
+    private final List<ProcedureCallNameSegment> procedureCallNames;
+    
+    private final List<ExpressionSegment> dynamicSqlStatementExpressions;
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
index 010dee48262..69b28bde8be 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
@@ -17,13 +17,30 @@
 
 package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
 
-import lombok.Setter;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateProcedureStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.CursorForLoopStatementSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Oracle create procedure statement.
  */
-@Setter
+@RequiredArgsConstructor
+@Getter
 public final class OracleCreateProcedureStatement extends 
CreateProcedureStatement implements OracleStatement {
+    
+    private final List<SQLStatementSegment> sqlStatements;
+    
+    private final List<ProcedureCallNameSegment> procedureCallNames;
+    
+    private final List<ExpressionSegment> dynamicSqlStatementExpressions;
+    
+    private final List<CursorForLoopStatementSegment> cursorForLoopStatements 
= new ArrayList<>();
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/CursorForLoopStatementSegment.java
similarity index 60%
copy from 
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
copy to 
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/CursorForLoopStatementSegment.java
index 83c66294cf9..270bca13f33 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/CursorForLoopStatementSegment.java
@@ -15,13 +15,31 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
+package 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql;
 
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateFunctionStatement;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+
+import java.util.Collection;
 
 /**
- * Oracle create function statement.
+ * Cursor for loop statement segment.
  */
-public final class OracleCreateFunctionStatement extends 
CreateFunctionStatement implements OracleStatement {
+@RequiredArgsConstructor
+@Getter
+public final class CursorForLoopStatementSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String record;
+    
+    private final String cursor;
+    
+    private final SQLStatement cursorRelatedStatement;
+    
+    private final Collection<SQLStatement> statements;
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/ProcedureCallNameSegment.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/ProcedureCallNameSegment.java
new file mode 100644
index 00000000000..a38503a91a4
--- /dev/null
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/ProcedureCallNameSegment.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.packages.PackageSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+
+import java.util.Optional;
+
+/**
+ * PL/SQL procedure call name segment.
+ */
+@RequiredArgsConstructor
+@Getter
+@Setter
+public final class ProcedureCallNameSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final IdentifierValue identifier;
+    
+    private PackageSegment packageSegment;
+    
+    public Optional<PackageSegment> getPackageSegment() {
+        return Optional.ofNullable(packageSegment);
+    }
+    
+    @Override
+    public String toString() {
+        return getPackageSegment().map(s -> 
s.getIdentifier().getValueWithQuoteCharacters() + ".").orElse("") + 
identifier.getValueWithQuoteCharacters();
+    }
+}
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/SQLStatementSegment.java
similarity index 69%
copy from 
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
copy to 
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/SQLStatementSegment.java
index 83c66294cf9..3a1fedb5ee6 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/SQLStatementSegment.java
@@ -15,13 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
+package 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql;
 
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateFunctionStatement;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
 /**
- * Oracle create function statement.
+ * SQL statement segment.
  */
-public final class OracleCreateFunctionStatement extends 
CreateFunctionStatement implements OracleStatement {
+@RequiredArgsConstructor
+@Getter
+public final class SQLStatementSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final SQLStatement sqlStatement;
 }
diff --git 
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
 
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
index a330216c29e..67e98e3e9a2 100644
--- 
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
+++ 
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
@@ -25,6 +25,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateFunctionStatement;
 import org.junit.jupiter.api.Test;
 
+import java.util.Collections;
 import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -51,7 +52,7 @@ class CreateFunctionStatementHandlerTest {
     @Test
     void assertGetRoutineBodySegmentForOtherDatabases() {
         assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new 
OpenGaussCreateFunctionStatement()).isPresent());
-        assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new 
OracleCreateFunctionStatement()).isPresent());
+        assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new 
OracleCreateFunctionStatement(Collections.emptyList(), Collections.emptyList(), 
Collections.emptyList())).isPresent());
         assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new 
PostgreSQLCreateFunctionStatement()).isPresent());
         assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new 
SQLServerCreateFunctionStatement()).isPresent());
     }
diff --git 
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
 
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
index 009059e623c..d0eca72b025 100644
--- 
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
+++ 
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
@@ -25,6 +25,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateProcedureStatement;
 import org.junit.jupiter.api.Test;
 
+import java.util.Collections;
 import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -51,7 +52,7 @@ class CreateProcedureStatementHandlerTest {
     @Test
     void assertGetRoutineBodySegmentForOtherDatabases() {
         assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new 
OpenGaussCreateProcedureStatement()).isPresent());
-        assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new 
OracleCreateProcedureStatement()).isPresent());
+        assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new 
OracleCreateProcedureStatement(Collections.emptyList(), 
Collections.emptyList(), Collections.emptyList())).isPresent());
         assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new 
PostgreSQLCreateProcedureStatement()).isPresent());
         assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new 
SQLServerCreateProcedureStatement()).isPresent());
     }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
index 95a5018c5cc..29f5fb390bd 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
@@ -29,17 +29,20 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dcl.DCLStatemen
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.tcl.TCLStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateFunctionStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateProcedureStatement;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.parameter.ParameterMarkerAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.comment.CommentAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.DALStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dcl.DCLStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.DDLStatementAssert;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dml.DMLStatementAssert;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.plsql.PLSQLStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ral.RALStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.rdl.RDLStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.rql.RQLStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.rul.RULStatementAssert;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dml.DMLStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.tcl.TCLStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
 
@@ -57,6 +60,10 @@ public final class SQLStatementAssert {
      * @param expected expected parser result
      */
     public static void assertIs(final SQLCaseAssertContext assertContext, 
final SQLStatement actual, final SQLParserTestCase expected) {
+        if (actual instanceof OracleCreateProcedureStatement || actual 
instanceof OracleCreateFunctionStatement) {
+            PLSQLStatementAssert.assertIs(assertContext, actual, expected);
+            return;
+        }
         ParameterMarkerAssert.assertCount(assertContext, 
actual.getParameterCount(), expected.getParameters().size());
         CommentAssert.assertComment(assertContext, actual, expected);
         if (actual instanceof DMLStatement) {
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/plsql/PLSQLStatementAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/plsql/PLSQLStatementAssert.java
new file mode 100644
index 00000000000..31795720692
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/plsql/PLSQLStatementAssert.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.plsql;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateFunctionStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateProcedureStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql.CreateFunctionTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql.CreateProcedureTestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * PL/SQL statement assert.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class PLSQLStatementAssert {
+    
+    /**
+     * Assert PL/SQL statement is correct with expected parser result.
+     *
+     * @param assertContext assert context
+     * @param actual actual PL/SQL statement
+     * @param expected expected parser result
+     */
+    public static void assertIs(final SQLCaseAssertContext assertContext, 
final SQLStatement actual, final SQLParserTestCase expected) {
+        if (actual instanceof OracleCreateProcedureStatement && expected 
instanceof CreateProcedureTestCase) {
+            OracleCreateProcedureStatement actualStatement = 
(OracleCreateProcedureStatement) actual;
+            CreateProcedureTestCase expectedTestCase = 
(CreateProcedureTestCase) expected;
+            assertProcedureName(assertContext, actualStatement, 
expectedTestCase);
+            assertSQLStatements(assertContext, 
actualStatement.getSqlStatements(), expectedTestCase.getSqlStatements());
+            assertProcedureCallNames(assertContext, 
actualStatement.getProcedureCallNames(), expectedTestCase.getProcedureCalls());
+            assertDynamicSqlStatementExpressions(assertContext, 
actualStatement.getDynamicSqlStatementExpressions(), 
expectedTestCase.getDynamicSqlStatementExpressions());
+        }
+        if (actual instanceof OracleCreateFunctionStatement && expected 
instanceof CreateFunctionTestCase) {
+            OracleCreateFunctionStatement actualStatement = 
(OracleCreateFunctionStatement) actual;
+            CreateFunctionTestCase expectedTestCase = (CreateFunctionTestCase) 
expected;
+            assertFunctionName(assertContext, actualStatement, 
expectedTestCase);
+            assertSQLStatements(assertContext, 
actualStatement.getSqlStatements(), expectedTestCase.getSqlStatements());
+            assertProcedureCallNames(assertContext, 
actualStatement.getProcedureCallNames(), expectedTestCase.getProcedureCalls());
+            assertDynamicSqlStatementExpressions(assertContext, 
actualStatement.getDynamicSqlStatementExpressions(), 
expectedTestCase.getDynamicSqlStatementExpressions());
+        }
+    }
+    
+    private static void assertProcedureName(final SQLCaseAssertContext 
assertContext, final OracleCreateProcedureStatement actual, final 
CreateProcedureTestCase expected) {
+        if (null == expected.getProcedureName()) {
+            assertFalse(actual.getProcedureName().isPresent(), 
assertContext.getText("Procedure name should not be exist."));
+        } else {
+            assertTrue(actual.getProcedureName().isPresent(), 
assertContext.getText("Procedure name should be exist."));
+            assertThat(assertContext.getText("Procedure name mismatched:"), 
actual.getProcedureName().get().getIdentifier().getValue(), 
is(expected.getProcedureName().getName()));
+        }
+    }
+    
+    private static void assertFunctionName(final SQLCaseAssertContext 
assertContext, final OracleCreateFunctionStatement actual, final 
CreateFunctionTestCase expected) {
+        if (null == expected.getFunctionName()) {
+            assertFalse(actual.getFunctionName().isPresent(), 
assertContext.getText("Function name should not be exist."));
+        } else {
+            assertTrue(actual.getFunctionName().isPresent(), 
assertContext.getText("Function name should be exist."));
+            assertThat(assertContext.getText("Function name mismatched:"), 
actual.getFunctionName().get().getIdentifier().getValue(), 
is(expected.getFunctionName().getName()));
+        }
+    }
+    
+    private static void assertSQLStatements(final SQLCaseAssertContext 
assertContext, final List<SQLStatementSegment> actual, final 
List<ExpectedSQLStatementSegment> expectedSQLStatementSegments) {
+        assertThat(assertContext.getText("SQL statements size mismatched: "), 
actual.size(), is(expectedSQLStatementSegments.size()));
+        List<SQLStatementSegment> actualSegments = new ArrayList<>(actual);
+        List<ExpectedSQLStatementSegment> expectedSegments = new 
ArrayList<>(expectedSQLStatementSegments);
+        for (int i = 0; i < actualSegments.size(); i++) {
+            SQLStatementSegment actualSegment = actualSegments.get(i);
+            ExpectedSQLStatementSegment expectedSegment = 
expectedSegments.get(i);
+            assertThat(assertContext.getText("Start index mismatched:"), 
actualSegment.getStartIndex(), is(expectedSegment.getStartIndex()));
+            assertThat(assertContext.getText("End index mismatched:"), 
actualSegment.getStopIndex(), is(expectedSegment.getStopIndex()));
+            assertThat(assertContext.getText("SQL statement mismatched:"), 
actualSegment.getSqlStatement().getClass().getSimpleName(), 
is(expectedSegment.getStatementClassSimpleName()));
+        }
+    }
+    
+    private static void assertProcedureCallNames(final SQLCaseAssertContext 
assertContext, final List<ProcedureCallNameSegment> actual,
+                                                 final 
List<ExpectedProcedureCallNameSegment> expectedProcedureCallSegments) {
+        assertThat(assertContext.getText("Procedure call names size 
mismatched: "), actual.size(), is(expectedProcedureCallSegments.size()));
+        List<ProcedureCallNameSegment> actualSegments = new 
ArrayList<>(actual);
+        List<ExpectedProcedureCallNameSegment> expectedSegments = new 
ArrayList<>(expectedProcedureCallSegments);
+        for (int i = 0; i < actualSegments.size(); i++) {
+            ProcedureCallNameSegment actualSegment = actualSegments.get(i);
+            ExpectedProcedureCallNameSegment expectedSegment = 
expectedSegments.get(i);
+            assertThat(assertContext.getText("Procedure call name 
mismatched:"), actualSegment.toString(), is(expectedSegment.getName()));
+        }
+    }
+    
+    private static void assertDynamicSqlStatementExpressions(final 
SQLCaseAssertContext assertContext, final List<ExpressionSegment> actual,
+                                                             final 
List<ExpectedDynamicSqlStatementExpressionSegment> expectedExpressionSegments) {
+        assertThat(assertContext.getText("Dynamic SQL statement expressions 
size mismatched: "), actual.size(), is(expectedExpressionSegments.size()));
+        List<ExpressionSegment> actualSegments = new ArrayList<>(actual);
+        List<ExpectedDynamicSqlStatementExpressionSegment> expectedSegments = 
new ArrayList<>(expectedExpressionSegments);
+        for (int i = 0; i < actualSegments.size(); i++) {
+            ExpressionSegment actualSegment = actualSegments.get(i);
+            ExpectedDynamicSqlStatementExpressionSegment expectedSegment = 
expectedSegments.get(i);
+            assertThat(assertContext.getText("Dynamic SQL statement start 
index mismatched: "), actualSegment.getStartIndex(), 
is(expectedSegment.getStartIndex()));
+            assertThat(assertContext.getText("Dynamic SQL statement stop index 
mismatched: "), actualSegment.getStopIndex(), 
is(expectedSegment.getStopIndex()));
+        }
+    }
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedDynamicSqlStatementExpressionSegment.java
similarity index 79%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedDynamicSqlStatementExpressionSegment.java
index bb3c5853ed5..15ab6bc27db 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedDynamicSqlStatementExpressionSegment.java
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
 
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
 
 /**
- * Create procedure statement test case.
+ * Expected dynamic SQL statement expression segment.
  */
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+public final class ExpectedDynamicSqlStatementExpressionSegment extends 
AbstractExpectedSQLSegment {
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedProcedureCallNameSegment.java
similarity index 71%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedProcedureCallNameSegment.java
index bb3c5853ed5..3fd04480a03 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedProcedureCallNameSegment.java
@@ -15,12 +15,21 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
 
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAttribute;
 
 /**
- * Create procedure statement test case.
+ * Expected procedure call name segment.
  */
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+@Getter
+@Setter
+public final class ExpectedProcedureCallNameSegment extends 
AbstractExpectedSQLSegment {
+    
+    @XmlAttribute
+    private String name;
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedRoutineName.java
similarity index 73%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedRoutineName.java
index bb3c5853ed5..0509d93cc15 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedRoutineName.java
@@ -15,12 +15,21 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
 
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAttribute;
 
 /**
- * Create procedure statement test case.
+ * Expected routine name.
  */
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+@Getter
+@Setter
+public final class ExpectedRoutineName extends AbstractExpectedSQLSegment {
+    
+    @XmlAttribute
+    private String name;
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedSQLStatementSegment.java
similarity index 69%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedSQLStatementSegment.java
index bb3c5853ed5..e2425bbcc87 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedSQLStatementSegment.java
@@ -15,12 +15,21 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
 
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAttribute;
 
 /**
- * Create procedure statement test case.
+ * Expected SQL statement segment.
  */
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+@Getter
+@Setter
+public final class ExpectedSQLStatementSegment extends 
AbstractExpectedSQLSegment {
+    
+    @XmlAttribute(name = "statement-class-simple-name")
+    private String statementClassSimpleName;
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
index 2cf7e238fac..b14876ea8ce 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
@@ -17,10 +17,38 @@
 
 package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
 
+import lombok.Getter;
+import lombok.Setter;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Create function statement test case.
  */
+@Getter
+@Setter
 public final class CreateFunctionStatementTestCase extends SQLParserTestCase {
+    
+    @XmlElement(name = "function-name")
+    private ExpectedRoutineName functionName;
+    
+    @XmlElementWrapper(name = "sql-statements")
+    @XmlElement(name = "sql-statement")
+    private List<ExpectedSQLStatementSegment> sqlStatements = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "procedure-calls")
+    @XmlElement(name = "procedure-call")
+    private List<ExpectedProcedureCallNameSegment> procedureCalls = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+    @XmlElement(name = "dynamic-sql-statement-expression")
+    private List<ExpectedDynamicSqlStatementExpressionSegment> 
dynamicSqlStatementExpressions = new LinkedList<>();
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
index bb3c5853ed5..d18d1ca17b0 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
@@ -17,10 +17,38 @@
 
 package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
 
+import lombok.Getter;
+import lombok.Setter;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Create procedure statement test case.
  */
+@Getter
+@Setter
 public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+    
+    @XmlElement(name = "procedure-name")
+    private ExpectedRoutineName procedureName;
+    
+    @XmlElementWrapper(name = "sql-statements")
+    @XmlElement(name = "sql-statement")
+    private List<ExpectedSQLStatementSegment> sqlStatements = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "procedure-calls")
+    @XmlElement(name = "procedure-call")
+    private List<ExpectedProcedureCallNameSegment> procedureCalls = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+    @XmlElement(name = "dynamic-sql-statement-expression")
+    private List<ExpectedDynamicSqlStatementExpressionSegment> 
dynamicSqlStatementExpressions = new LinkedList<>();
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateFunctionTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateFunctionTestCase.java
new file mode 100644
index 00000000000..0788d2c5170
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateFunctionTestCase.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql;
+
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Oracle create function test case.
+ */
+@Getter
+@Setter
+public final class CreateFunctionTestCase extends SQLParserTestCase {
+    
+    @XmlElement(name = "function-name")
+    private ExpectedRoutineName functionName;
+    
+    @XmlElementWrapper(name = "sql-statements")
+    @XmlElement(name = "sql-statement")
+    private List<ExpectedSQLStatementSegment> sqlStatements = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "procedure-calls")
+    @XmlElement(name = "procedure-call")
+    private List<ExpectedProcedureCallNameSegment> procedureCalls = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+    @XmlElement(name = "dynamic-sql-statement-expression")
+    private List<ExpectedDynamicSqlStatementExpressionSegment> 
dynamicSqlStatementExpressions = new LinkedList<>();
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateProcedureTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateProcedureTestCase.java
new file mode 100644
index 00000000000..fe02ef653ab
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateProcedureTestCase.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql;
+
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Oracle create procedure test case.
+ */
+@Getter
+@Setter
+public final class CreateProcedureTestCase extends SQLParserTestCase {
+    
+    @XmlElement(name = "procedure-name")
+    private ExpectedRoutineName procedureName;
+    
+    @XmlElementWrapper(name = "sql-statements")
+    @XmlElement(name = "sql-statement")
+    private List<ExpectedSQLStatementSegment> sqlStatements = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "procedure-calls")
+    @XmlElement(name = "procedure-call")
+    private List<ExpectedProcedureCallNameSegment> procedureCalls = new 
LinkedList<>();
+    
+    @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+    @XmlElement(name = "dynamic-sql-statement-expression")
+    private List<ExpectedDynamicSqlStatementExpressionSegment> 
dynamicSqlStatementExpressions = new LinkedList<>();
+}
diff --git a/test/it/parser/src/main/resources/case/plsql/create-function.xml 
b/test/it/parser/src/main/resources/case/plsql/create-function.xml
new file mode 100644
index 00000000000..25c85ada135
--- /dev/null
+++ b/test/it/parser/src/main/resources/case/plsql/create-function.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<sql-parser-test-cases>
+    <create-function sql-case-id="pl_sql_create_function" />
+</sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/case/plsql/create-procedure.xml 
b/test/it/parser/src/main/resources/case/plsql/create-procedure.xml
new file mode 100644
index 00000000000..44d0f76e012
--- /dev/null
+++ b/test/it/parser/src/main/resources/case/plsql/create-procedure.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<sql-parser-test-cases>
+    <create-procedure sql-case-id="pl_sql_create_procedure">
+        <procedure-name name="test_procedure" />
+        <sql-statements>
+            <sql-statement start-index="167" stop-index="192" 
statement-class-simple-name="OracleSavepointStatement" />
+            <sql-statement start-index="210" stop-index="274" 
statement-class-simple-name="OracleSelectStatement" />
+            <sql-statement start-index="1205" stop-index="1210" 
statement-class-simple-name="OracleCommitStatement" />
+            <sql-statement start-index="1251" stop-index="1293" 
statement-class-simple-name="OracleRollbackStatement" />
+            <sql-statement start-index="1408" stop-index="1450" 
statement-class-simple-name="OracleRollbackStatement" />
+        </sql-statements>
+        <procedure-calls>
+            <procedure-call name="DBMS_OUTPUT.PUT_LINE" />
+            <procedure-call name="DBMS_OUTPUT.PUT_LINE" />
+        </procedure-calls>
+    </create-procedure>
+</sql-parser-test-cases>
diff --git 
a/test/it/parser/src/main/resources/sql/supported/plsql/create-function.xml 
b/test/it/parser/src/main/resources/sql/supported/plsql/create-function.xml
new file mode 100644
index 00000000000..6346f011538
--- /dev/null
+++ b/test/it/parser/src/main/resources/sql/supported/plsql/create-function.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<sql-cases>
+    <sql-case id="pl_sql_create_function" db-types="Oracle" 
case-types="LITERAL" value="CREATE OR REPLACE EDITIONABLE FUNCTION 
&quot;TEST&quot;.&quot;test_function&quot; ( v_orgid IN NUMBER)&#10;        
RETURN NUMBER AS&#10;           v_partAmount NUMBER(9,2);--兼岗人数&#10;           
v_factnums NUMBER(9,2);--实际人数&#10;           v_cnt NUMBER;&#10;&#10;        
BEGIN&#10;&#10;          v_factnums:=0;&#10;          
v_partAmount:=0;&#10;&#10;        BEGIN--1&#10;              --- 部门实际的兼岗人数&#10; 
 [...]
+</sql-cases>
diff --git 
a/test/it/parser/src/main/resources/sql/supported/plsql/create-procedure.xml 
b/test/it/parser/src/main/resources/sql/supported/plsql/create-procedure.xml
new file mode 100644
index 00000000000..747de6ebeca
--- /dev/null
+++ b/test/it/parser/src/main/resources/sql/supported/plsql/create-procedure.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<sql-cases>
+    <sql-case id="pl_sql_create_procedure" db-types="Oracle"  value="create or 
replace procedure test_procedure(P_RETVAL out varchar2) is   E_EXCEPTION 
EXCEPTION;   v_bendate date;   v_enddate date;   v_day     varchar2(30); begin 
SAVEPOINT cp_SHOPBudget_Gy; P_RETVAL := 0; select upper(trim(to_char(sysdate, 
'day'))) into v_day from dual; if v_day = 'MONDAY' then     return; else     
case       when v_day = 'MONDAY' then         v_bendate := TRUNC(SYSDATE) - 7;  
       v_enddate := TRUNC( [...]
+</sql-cases>


Reply via email to