You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by pa...@apache.org on 2021/08/22 04:23:59 UTC

[shardingsphere] branch master updated: Add Oracle SQL - Update statement (#11692)

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

panjuan 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 3c51144  Add Oracle SQL - Update statement (#11692)
3c51144 is described below

commit 3c51144dafb300617a9a84558b6d87704f826c6a
Author: Thanoshan MV <48...@users.noreply.github.com>
AuthorDate: Sun Aug 22 09:53:28 2021 +0530

    Add Oracle SQL - Update statement (#11692)
    
    * add oracle update definition
    
    * add multi-column in an assignment
    
    * make AssignmentSegment into abstract, define new ColumnAssignmentSegment and refactor AssignmentSegment related code.
    
    * utilize ColumnAssignmentSegment to create an instance type of AssignmentSegment
    
    * set ColumnAssignmentSegment's columns field to final and uninitialize it
    
    * remove commented code
---
 .../impl/EncryptAssignmentParameterRewriter.java   |   4 +-
 .../impl/EncryptAssignmentTokenGenerator.java      |  18 +-
 .../impl/EncryptInsertOnUpdateTokenGenerator.java  |  19 +-
 .../impl/ShadowUpdateValueParameterRewriter.java   |   4 +-
 .../impl/ShadowUpdateColumnTokenGenerator.java     |   4 +-
 .../ShadowUpdateValueParameterRewriterTest.java    |   8 +-
 .../impl/ShadowUpdateColumnTokenGeneratorTest.java |   7 +-
 .../dml/impl/ShardingInsertStatementValidator.java |   2 +-
 .../dml/impl/ShardingUpdateStatementValidator.java |   2 +-
 .../dml/ShardingInsertStatementValidatorTest.java  |   5 +-
 .../dml/ShardingUpdateStatementValidatorTest.java  |  13 +-
 .../insert/values/OnDuplicateUpdateContext.java    |   2 +-
 .../statement/dml/InsertStatementContext.java      |   2 +-
 .../values/OnDuplicateUpdateContextTest.java       |   9 +-
 .../statement/SQLStatementContextFactoryTest.java  |   8 +-
 .../statement/impl/InsertStatementContextTest.java |  26 +-
 .../statement/impl/MySQLStatementSQLVisitor.java   |   6 +-
 .../src/main/antlr4/imports/oracle/DMLStatement.g4 |  21 +-
 .../impl/OracleDMLStatementSQLVisitor.java         | 117 +++++++--
 .../impl/PostgreSQLStatementSQLVisitor.java        |   6 +-
 .../impl/SQL92DMLStatementSQLVisitor.java          |   7 +-
 .../impl/SQLServerDMLStatementSQLVisitor.java      |   7 +-
 .../sql/common/extractor/TableExtractor.java       |   2 +-
 .../segment/dml/assignment/AssignmentSegment.java  |  28 ++-
 ...ntSegment.java => ColumnAssignmentSegment.java} |   9 +-
 .../segment/assignment/AssignmentAssert.java       |  21 +-
 .../segment/assignment/AssignmentValueAssert.java  |   3 +
 .../impl/assignment/ExpectedAssignment.java        |   4 +
 .../impl/assignment/ExpectedAssignmentValue.java   |   4 +
 .../src/main/resources/case/dml/update.xml         | 273 +++++++++++++++++----
 .../main/resources/sql/supported/dml/update.xml    |   6 +-
 31 files changed, 509 insertions(+), 138 deletions(-)

diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/parameter/impl/EncryptAssignmentParameterRewriter.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/parameter/impl/EncryptAssignmentParameterRewriter.java
index 6762a08..68117a9 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/parameter/impl/EncryptAssignmentParameterRewriter.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/parameter/impl/EncryptAssignmentParameterRewriter.java
@@ -60,7 +60,7 @@ public final class EncryptAssignmentParameterRewriter extends EncryptParameterRe
     public void rewrite(final ParameterBuilder parameterBuilder, final SQLStatementContext sqlStatementContext, final List<Object> parameters) {
         String tableName = ((TableAvailable) sqlStatementContext).getAllTables().iterator().next().getTableName().getIdentifier().getValue();
         for (AssignmentSegment each : getSetAssignmentSegment(sqlStatementContext.getSqlStatement()).getAssignments()) {
-            if (each.getValue() instanceof ParameterMarkerExpressionSegment && getEncryptRule().findEncryptor(tableName, each.getColumn().getIdentifier().getValue()).isPresent()) {
+            if (each.getValue() instanceof ParameterMarkerExpressionSegment && getEncryptRule().findEncryptor(tableName, each.getColumns().get(0).getIdentifier().getValue()).isPresent()) {
                 StandardParameterBuilder standardParameterBuilder = parameterBuilder instanceof StandardParameterBuilder
                         ? (StandardParameterBuilder) parameterBuilder : ((GroupedParameterBuilder) parameterBuilder).getParameterBuilders().get(0);
                 encryptParameters(standardParameterBuilder, tableName, each, parameters);
@@ -78,7 +78,7 @@ public final class EncryptAssignmentParameterRewriter extends EncryptParameterRe
     }
     
     private void encryptParameters(final StandardParameterBuilder parameterBuilder, final String tableName, final AssignmentSegment assignmentSegment, final List<Object> parameters) {
-        String columnName = assignmentSegment.getColumn().getIdentifier().getValue();
+        String columnName = assignmentSegment.getColumns().get(0).getIdentifier().getValue();
         int parameterMarkerIndex = ((ParameterMarkerExpressionSegment) assignmentSegment.getValue()).getParameterMarkerIndex();
         Object originalValue = parameters.get(parameterMarkerIndex);
         Object cipherValue = getEncryptRule().getEncryptValues(tableName, columnName, Collections.singletonList(originalValue)).iterator().next();
diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptAssignmentTokenGenerator.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptAssignmentTokenGenerator.java
index 55931b6..c9898d8 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptAssignmentTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptAssignmentTokenGenerator.java
@@ -57,7 +57,7 @@ public final class EncryptAssignmentTokenGenerator extends BaseEncryptSQLTokenGe
         Collection<EncryptAssignmentToken> result = new LinkedList<>();
         String tableName = ((TableAvailable) sqlStatementContext).getAllTables().iterator().next().getTableName().getIdentifier().getValue();
         for (AssignmentSegment each : getSetAssignmentSegment(sqlStatementContext.getSqlStatement()).getAssignments()) {
-            if (getEncryptRule().findEncryptor(tableName, each.getColumn().getIdentifier().getValue()).isPresent()) {
+            if (getEncryptRule().findEncryptor(tableName, each.getColumns().get(0).getIdentifier().getValue()).isPresent()) {
                 generateSQLToken(tableName, each).ifPresent(result::add);
             }
         }
@@ -84,8 +84,8 @@ public final class EncryptAssignmentTokenGenerator extends BaseEncryptSQLTokenGe
     }
     
     private EncryptAssignmentToken generateParameterSQLToken(final String tableName, final AssignmentSegment assignmentSegment) {
-        EncryptParameterAssignmentToken result = new EncryptParameterAssignmentToken(assignmentSegment.getColumn().getStartIndex(), assignmentSegment.getStopIndex());
-        String columnName = assignmentSegment.getColumn().getIdentifier().getValue();
+        EncryptParameterAssignmentToken result = new EncryptParameterAssignmentToken(assignmentSegment.getColumns().get(0).getStartIndex(), assignmentSegment.getStopIndex());
+        String columnName = assignmentSegment.getColumns().get(0).getIdentifier().getValue();
         addCipherColumn(tableName, columnName, result);
         addAssistedQueryColumn(tableName, columnName, result);
         addPlainColumn(tableName, columnName, result);
@@ -105,7 +105,7 @@ public final class EncryptAssignmentTokenGenerator extends BaseEncryptSQLTokenGe
     }
     
     private EncryptAssignmentToken generateLiteralSQLToken(final String tableName, final AssignmentSegment assignmentSegment) {
-        EncryptLiteralAssignmentToken result = new EncryptLiteralAssignmentToken(assignmentSegment.getColumn().getStartIndex(), assignmentSegment.getStopIndex());
+        EncryptLiteralAssignmentToken result = new EncryptLiteralAssignmentToken(assignmentSegment.getColumns().get(0).getStartIndex(), assignmentSegment.getStopIndex());
         addCipherAssignment(tableName, assignmentSegment, result);
         addAssistedQueryAssignment(tableName, assignmentSegment, result);
         addPlainAssignment(tableName, assignmentSegment, result);
@@ -114,22 +114,22 @@ public final class EncryptAssignmentTokenGenerator extends BaseEncryptSQLTokenGe
     
     private void addCipherAssignment(final String tableName, final AssignmentSegment assignmentSegment, final EncryptLiteralAssignmentToken token) {
         Object originalValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
-        Object cipherValue = getEncryptRule().getEncryptValues(tableName, assignmentSegment.getColumn().getIdentifier().getValue(), Collections.singletonList(originalValue)).iterator().next();
-        token.addAssignment(getEncryptRule().getCipherColumn(tableName, assignmentSegment.getColumn().getIdentifier().getValue()), cipherValue);
+        Object cipherValue = getEncryptRule().getEncryptValues(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue(), Collections.singletonList(originalValue)).iterator().next();
+        token.addAssignment(getEncryptRule().getCipherColumn(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue()), cipherValue);
     }
     
     private void addAssistedQueryAssignment(final String tableName, final AssignmentSegment assignmentSegment, final EncryptLiteralAssignmentToken token) {
         Object originalValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
-        Optional<String> assistedQueryColumn = getEncryptRule().findAssistedQueryColumn(tableName, assignmentSegment.getColumn().getIdentifier().getValue());
+        Optional<String> assistedQueryColumn = getEncryptRule().findAssistedQueryColumn(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue());
         assistedQueryColumn.ifPresent(s -> {
             Object assistedQueryValue = getEncryptRule().getEncryptAssistedQueryValues(
-                    tableName, assignmentSegment.getColumn().getIdentifier().getValue(), Collections.singletonList(originalValue)).iterator().next();
+                    tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue(), Collections.singletonList(originalValue)).iterator().next();
             token.addAssignment(s, assistedQueryValue);
         });
     }
     
     private void addPlainAssignment(final String tableName, final AssignmentSegment assignmentSegment, final EncryptLiteralAssignmentToken token) {
         Object originalValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
-        getEncryptRule().findPlainColumn(tableName, assignmentSegment.getColumn().getIdentifier().getValue()).ifPresent(plainColumn -> token.addAssignment(plainColumn, originalValue));
+        getEncryptRule().findPlainColumn(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue()).ifPresent(plainColumn -> token.addAssignment(plainColumn, originalValue));
     }
 }
diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptInsertOnUpdateTokenGenerator.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptInsertOnUpdateTokenGenerator.java
index a140ca2..66ca4ee 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptInsertOnUpdateTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptInsertOnUpdateTokenGenerator.java
@@ -60,7 +60,7 @@ public final class EncryptInsertOnUpdateTokenGenerator extends BaseEncryptSQLTok
             return result;
         }
         for (AssignmentSegment each : onDuplicateKeyColumnsSegments) {
-            if (getEncryptRule().findEncryptor(tableName, each.getColumn().getIdentifier().getValue()).isPresent()) {
+            if (getEncryptRule().findEncryptor(tableName, each.getColumns().get(0).getIdentifier().getValue()).isPresent()) {
                 generateSQLToken(tableName, each).ifPresent(result::add);
             }
         }
@@ -78,8 +78,8 @@ public final class EncryptInsertOnUpdateTokenGenerator extends BaseEncryptSQLTok
     }
     
     private EncryptAssignmentToken generateParameterSQLToken(final String tableName, final AssignmentSegment assignmentSegment) {
-        EncryptParameterAssignmentToken result = new EncryptParameterAssignmentToken(assignmentSegment.getColumn().getStartIndex(), assignmentSegment.getStopIndex());
-        String columnName = assignmentSegment.getColumn().getIdentifier().getValue();
+        EncryptParameterAssignmentToken result = new EncryptParameterAssignmentToken(assignmentSegment.getColumns().get(0).getStartIndex(), assignmentSegment.getStopIndex());
+        String columnName = assignmentSegment.getColumns().get(0).getIdentifier().getValue();
         addCipherColumn(tableName, columnName, result);
         addAssistedQueryColumn(tableName, columnName, result);
         addPlainColumn(tableName, columnName, result);
@@ -87,7 +87,7 @@ public final class EncryptInsertOnUpdateTokenGenerator extends BaseEncryptSQLTok
     }
     
     private EncryptAssignmentToken generateLiteralSQLToken(final String tableName, final AssignmentSegment assignmentSegment) {
-        EncryptLiteralAssignmentToken result = new EncryptLiteralAssignmentToken(assignmentSegment.getColumn().getStartIndex(), assignmentSegment.getStopIndex());
+        EncryptLiteralAssignmentToken result = new EncryptLiteralAssignmentToken(assignmentSegment.getColumns().get(0).getStartIndex(), assignmentSegment.getStopIndex());
         addCipherAssignment(tableName, assignmentSegment, result);
         addAssistedQueryAssignment(tableName, assignmentSegment, result);
         addPlainAssignment(tableName, assignmentSegment, result);
@@ -108,14 +108,15 @@ public final class EncryptInsertOnUpdateTokenGenerator extends BaseEncryptSQLTok
     
     private void addCipherAssignment(final String tableName, final AssignmentSegment assignmentSegment, final EncryptLiteralAssignmentToken token) {
         Object originalValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
-        Object cipherValue = getEncryptRule().getEncryptValues(tableName, assignmentSegment.getColumn().getIdentifier().getValue(), Collections.singletonList(originalValue)).iterator().next();
-        token.addAssignment(getEncryptRule().getCipherColumn(tableName, assignmentSegment.getColumn().getIdentifier().getValue()), cipherValue);
+        Object cipherValue = getEncryptRule().getEncryptValues(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue(), Collections.singletonList(originalValue)).iterator().next();
+        token.addAssignment(getEncryptRule().getCipherColumn(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue()), cipherValue);
     }
     
     private void addAssistedQueryAssignment(final String tableName, final AssignmentSegment assignmentSegment, final EncryptLiteralAssignmentToken token) {
-        getEncryptRule().findAssistedQueryColumn(tableName, assignmentSegment.getColumn().getIdentifier().getValue()).ifPresent(assistedQueryColumn -> {
+        getEncryptRule().findAssistedQueryColumn(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue()).ifPresent(assistedQueryColumn -> {
             Object originalValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
-            Object assistedQueryValue = getEncryptRule().getEncryptAssistedQueryValues(tableName, assignmentSegment.getColumn().getIdentifier().getValue(), Collections.singletonList(originalValue))
+            Object assistedQueryValue = getEncryptRule()
+                    .getEncryptAssistedQueryValues(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue(), Collections.singletonList(originalValue))
                     .iterator().next();
             token.addAssignment(assistedQueryColumn, assistedQueryValue);
         });
@@ -123,6 +124,6 @@ public final class EncryptInsertOnUpdateTokenGenerator extends BaseEncryptSQLTok
     
     private void addPlainAssignment(final String tableName, final AssignmentSegment assignmentSegment, final EncryptLiteralAssignmentToken token) {
         Object originalValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
-        getEncryptRule().findPlainColumn(tableName, assignmentSegment.getColumn().getIdentifier().getValue()).ifPresent(plainColumn -> token.addAssignment(plainColumn, originalValue));
+        getEncryptRule().findPlainColumn(tableName, assignmentSegment.getColumns().get(0).getIdentifier().getValue()).ifPresent(plainColumn -> token.addAssignment(plainColumn, originalValue));
     }
 }
diff --git a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriter.java b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriter.java
index 9bd3afd..cd898fa 100644
--- a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriter.java
+++ b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriter.java
@@ -38,7 +38,7 @@ public final class ShadowUpdateValueParameterRewriter extends ShadowParameterRew
     }
     
     private boolean isContainShadowColumn(final UpdateStatement updateStatement) {
-        return updateStatement.getSetAssignment().getAssignments().stream().anyMatch(each -> each.getColumn().getIdentifier().getValue().equals(getShadowColumn()));
+        return updateStatement.getSetAssignment().getAssignments().stream().anyMatch(each -> each.getColumns().get(0).getIdentifier().getValue().equals(getShadowColumn()));
     }
     
     @Override
@@ -55,7 +55,7 @@ public final class ShadowUpdateValueParameterRewriter extends ShadowParameterRew
     private int getShadowColumnIndex(final UpdateStatement sqlStatement) {
         int count = 0;
         for (AssignmentSegment each : sqlStatement.getSetAssignment().getAssignments()) {
-            if (each.getColumn().getIdentifier().getValue().equals(getShadowColumn())) {
+            if (each.getColumns().get(0).getIdentifier().getValue().equals(getShadowColumn())) {
                 return count;
             }
             count++;
diff --git a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGenerator.java b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGenerator.java
index 80311f4..7d966b1 100644
--- a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGenerator.java
@@ -42,7 +42,7 @@ public final class ShadowUpdateColumnTokenGenerator extends BaseShadowSQLTokenGe
     }
     
     private boolean isContainShadowColumn(final Collection<AssignmentSegment> assignments) {
-        return assignments.stream().anyMatch(each -> each.getColumn().getIdentifier().getValue().equals(getShadowColumn()));
+        return assignments.stream().anyMatch(each -> each.getColumns().get(0).getIdentifier().getValue().equals(getShadowColumn()));
     }
     
     @Override
@@ -52,7 +52,7 @@ public final class ShadowUpdateColumnTokenGenerator extends BaseShadowSQLTokenGe
     
     private Collection<RemoveToken> generateRemoveTokenForShadow(final Collection<AssignmentSegment> assignments) {
         List<AssignmentSegment> assignmentSegments = (LinkedList<AssignmentSegment>) assignments;
-        return IntStream.range(0, assignmentSegments.size()).filter(i -> getShadowColumn().equals(assignmentSegments.get(i).getColumn().getIdentifier().getValue()))
+        return IntStream.range(0, assignmentSegments.size()).filter(i -> getShadowColumn().equals(assignmentSegments.get(i).getColumns().get(0).getIdentifier().getValue()))
                 .mapToObj(i -> createRemoveToken(assignmentSegments, i)).collect(Collectors.toCollection(LinkedList::new));
     }
     
diff --git a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriterTest.java b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriterTest.java
index 6b4176d..f85d099 100644
--- a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriterTest.java
+++ b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/parameter/impl/ShadowUpdateValueParameterRewriterTest.java
@@ -21,6 +21,7 @@ import org.apache.shardingsphere.infra.binder.statement.dml.UpdateStatementConte
 import org.apache.shardingsphere.infra.rewrite.parameter.builder.impl.GroupedParameterBuilder;
 import org.apache.shardingsphere.shadow.rule.ShadowRule;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
@@ -31,6 +32,8 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -56,7 +59,10 @@ public final class ShadowUpdateValueParameterRewriterTest {
     }
     
     private SetAssignmentSegment createSetAssignmentSegment(final String shadowColumn) {
-        return new SetAssignmentSegment(0, 20, Collections.singletonList(new AssignmentSegment(0, 15, new ColumnSegment(0, 15, new IdentifierValue(shadowColumn)), mock(ExpressionSegment.class))));
+        List<ColumnSegment> columns = new LinkedList<>();
+        columns.add(new ColumnSegment(0, 15, new IdentifierValue(shadowColumn)));
+        AssignmentSegment assignment = new ColumnAssignmentSegment(0, 15, columns, mock(ExpressionSegment.class));
+        return new SetAssignmentSegment(0, 20, Collections.singletonList(assignment));
     }
     
     private void initShadowUpdateValueParameterRewriter(final String shadowColumn) {
diff --git a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGeneratorTest.java b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGeneratorTest.java
index 8b10ae0..e65b771 100644
--- a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGeneratorTest.java
+++ b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/test/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowUpdateColumnTokenGeneratorTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.shadow.rewrite.token.generator.impl;
 import org.apache.shardingsphere.infra.binder.statement.dml.UpdateStatementContext;
 import org.apache.shardingsphere.shadow.rule.ShadowRule;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
@@ -31,6 +32,7 @@ import org.junit.Test;
 
 import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
@@ -65,7 +67,10 @@ public final class ShadowUpdateColumnTokenGeneratorTest {
     }
     
     private AssignmentSegment createAssignmentSegment(final int startIndex, final int stopIndex, final IdentifierValue identifierValue) {
-        return new AssignmentSegment(startIndex, stopIndex, new ColumnSegment(startIndex, stopIndex, identifierValue), mock(ExpressionSegment.class));
+        List<ColumnSegment> columns = new LinkedList<>();
+        columns.add(new ColumnSegment(startIndex, stopIndex, identifierValue));
+        AssignmentSegment result = new ColumnAssignmentSegment(startIndex, stopIndex, columns, mock(ExpressionSegment.class));
+        return result;
     }
     
     private void initShadowUpdateColumnTokenGenerator(final String shadowColumn) {
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingInsertStatementValidator.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingInsertStatementValidator.java
index 69a502f..3eff253 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingInsertStatementValidator.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingInsertStatementValidator.java
@@ -72,7 +72,7 @@ public final class ShardingInsertStatementValidator extends ShardingDMLStatement
     
     private boolean isUpdateShardingKey(final ShardingRule shardingRule, final OnDuplicateKeyColumnsSegment onDuplicateKeyColumnsSegment, final String tableName) {
         for (AssignmentSegment each : onDuplicateKeyColumnsSegment.getColumns()) {
-            if (shardingRule.isShardingColumn(each.getColumn().getIdentifier().getValue(), tableName)) {
+            if (shardingRule.isShardingColumn(each.getColumns().get(0).getIdentifier().getValue(), tableName)) {
                 return true;
             }
         }
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingUpdateStatementValidator.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingUpdateStatementValidator.java
index 2f95141..4d23ec8 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingUpdateStatementValidator.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingUpdateStatementValidator.java
@@ -50,7 +50,7 @@ public final class ShardingUpdateStatementValidator extends ShardingDMLStatement
         UpdateStatement sqlStatement = sqlStatementContext.getSqlStatement();
         String tableName = sqlStatementContext.getTablesContext().getTables().iterator().next().getTableName().getIdentifier().getValue();
         for (AssignmentSegment each : sqlStatement.getSetAssignment().getAssignments()) {
-            String shardingColumn = each.getColumn().getIdentifier().getValue();
+            String shardingColumn = each.getColumns().get(0).getIdentifier().getValue();
             if (shardingRule.isShardingColumn(shardingColumn, tableName)) {
                 Optional<Object> shardingColumnSetAssignmentValue = getShardingColumnSetAssignmentValue(each, parameters);
                 Optional<Object> shardingValue = Optional.empty();
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingInsertStatementValidatorTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingInsertStatementValidatorTest.java
index b29dac8..0ea8fda 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingInsertStatementValidatorTest.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingInsertStatementValidatorTest.java
@@ -30,6 +30,7 @@ import org.apache.shardingsphere.sharding.route.engine.condition.ShardingConditi
 import org.apache.shardingsphere.sharding.route.engine.validator.dml.impl.ShardingInsertStatementValidator;
 import org.apache.shardingsphere.sharding.rule.ShardingRule;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.InsertColumnsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
@@ -198,7 +199,9 @@ public final class ShardingInsertStatementValidatorTest {
         MySQLInsertStatement result = new MySQLInsertStatement();
         result.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("user"))));
         ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("id"));
-        AssignmentSegment assignmentSegment = new AssignmentSegment(0, 0, columnSegment, new ParameterMarkerExpressionSegment(0, 0, 1));
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(columnSegment);
+        AssignmentSegment assignmentSegment = new ColumnAssignmentSegment(0, 0, columnSegments, new ParameterMarkerExpressionSegment(0, 0, 1));
         result.setOnDuplicateKeyColumns(new OnDuplicateKeyColumnsSegment(0, 0, Collections.singletonList(assignmentSegment)));
         Collection<ColumnSegment> columns = new LinkedList<>();
         columns.add(columnSegment);
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingUpdateStatementValidatorTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingUpdateStatementValidatorTest.java
index 19a3141..cfb54ef 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingUpdateStatementValidatorTest.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/test/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/ShardingUpdateStatementValidatorTest.java
@@ -24,6 +24,7 @@ import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
 import org.apache.shardingsphere.sharding.route.engine.validator.dml.impl.ShardingUpdateStatementValidator;
 import org.apache.shardingsphere.sharding.rule.ShardingRule;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
@@ -44,6 +45,7 @@ import org.mockito.junit.MockitoJUnitRunner;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 
 import static org.mockito.Mockito.mock;
@@ -105,16 +107,21 @@ public final class ShardingUpdateStatementValidatorTest {
     private UpdateStatement createUpdateStatement() {
         UpdateStatement result = new MySQLUpdateStatement();
         result.setTableSegment(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("user"))));
+        List<ColumnSegment> columns = new LinkedList<>();
+        columns.add(new ColumnSegment(0, 0, new IdentifierValue("id")));
+        AssignmentSegment assignment = new ColumnAssignmentSegment(0, 0, columns, new LiteralExpressionSegment(0, 0, ""));
         result.setSetAssignment(
-                new SetAssignmentSegment(0, 0, Collections.singletonList(new AssignmentSegment(0, 0, new ColumnSegment(0, 0, new IdentifierValue("id")), new LiteralExpressionSegment(0, 0, "")))));
+                new SetAssignmentSegment(0, 0, Collections.singletonList(assignment)));
         return result;
     }
     
     private UpdateStatement createUpdateStatementAndParameters(final Object shardingColumnParameter) {
         UpdateStatement result = new MySQLUpdateStatement();
         result.setTableSegment(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("user"))));
-        Collection<AssignmentSegment> assignments = Collections.singletonList(
-                new AssignmentSegment(0, 0, new ColumnSegment(0, 0, new IdentifierValue("id")), new LiteralExpressionSegment(0, 0, shardingColumnParameter)));
+        List<ColumnSegment> columns = new LinkedList<>();
+        columns.add(new ColumnSegment(0, 0, new IdentifierValue("id")));
+        AssignmentSegment assignment = new ColumnAssignmentSegment(0, 0, columns, new LiteralExpressionSegment(0, 0, shardingColumnParameter));
+        Collection<AssignmentSegment> assignments = Collections.singletonList(assignment);
         SetAssignmentSegment setAssignmentSegment = new SetAssignmentSegment(0, 0, assignments);
         result.setSetAssignment(setAssignmentSegment);
         ColumnSegment left = new ColumnSegment(0, 0, new IdentifierValue("id"));
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContext.java b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContext.java
index b961fbe..b70a105 100644
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContext.java
+++ b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContext.java
@@ -48,7 +48,7 @@ public final class OnDuplicateUpdateContext {
         parameterCount = calculateParameterCount(expressionSegments);
         valueExpressions = getValueExpressions(expressionSegments);
         this.parameters = getParameters(parameters, parametersOffset);
-        columns = assignments.stream().map(AssignmentSegment::getColumn).collect(Collectors.toList());
+        columns = assignments.stream().map(assignment -> assignment.getColumns().get(0)).collect(Collectors.toList());
     }
     
     private int calculateParameterCount(final Collection<ExpressionSegment> assignments) {
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementContext.java b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementContext.java
index 1ddd6b9..7b50aa9 100644
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementContext.java
+++ b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementContext.java
@@ -218,7 +218,7 @@ public final class InsertStatementContext extends CommonSQLStatementContext<Inse
     private List<String> getColumnNamesForSetAssignment(final SetAssignmentSegment setAssignment) {
         List<String> result = new LinkedList<>();
         for (AssignmentSegment each : setAssignment.getAssignments()) {
-            result.add(each.getColumn().getIdentifier().getValue().toLowerCase());
+            result.add(each.getColumns().get(0).getIdentifier().getValue().toLowerCase());
         }
         return result;
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContextTest.java b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContextTest.java
index 006eb8d..afc7055 100644
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContextTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/insert/values/OnDuplicateUpdateContextTest.java
@@ -18,6 +18,7 @@
 package org.apache.shardingsphere.infra.binder.segment.insert.values;
 
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 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.simple.LiteralExpressionSegment;
@@ -31,6 +32,7 @@ import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -102,7 +104,10 @@ public final class OnDuplicateUpdateContextTest {
         int doesNotMatterLexicalIndex = 0;
         String doesNotMatterColumnName = "columnNameStr";
         ColumnSegment column = new ColumnSegment(doesNotMatterLexicalIndex, doesNotMatterLexicalIndex, new IdentifierValue(doesNotMatterColumnName));
-        return new AssignmentSegment(doesNotMatterLexicalIndex, doesNotMatterLexicalIndex, column, expressionSegment);
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(column);
+        AssignmentSegment result = new ColumnAssignmentSegment(doesNotMatterLexicalIndex, doesNotMatterLexicalIndex, columnSegments, expressionSegment);
+        return result;
     }
     
     @Test
@@ -130,6 +135,6 @@ public final class OnDuplicateUpdateContextTest {
         List<Object> parameters = Collections.emptyList();
         OnDuplicateUpdateContext onDuplicateUpdateContext = new OnDuplicateUpdateContext(assignments, parameters, 0);
         ColumnSegment column = onDuplicateUpdateContext.getColumn(0);
-        assertThat(column, is(assignments.iterator().next().getColumn()));
+        assertThat(column, is(assignments.iterator().next().getColumns().get(0)));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementContextFactoryTest.java b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementContextFactoryTest.java
index 5108963..bd44fca 100644
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementContextFactoryTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementContextFactoryTest.java
@@ -23,6 +23,7 @@ import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementConte
 import org.apache.shardingsphere.infra.database.DefaultSchema;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
@@ -41,6 +42,8 @@ import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.dml.
 import org.junit.Test;
 
 import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 import static org.junit.Assert.assertNotNull;
@@ -64,8 +67,11 @@ public final class SQLStatementContextFactoryTest {
     @Test
     public void assertSQLStatementContextCreatedWhenSQLStatementInstanceOfMySQLInsertStatement() {
         MySQLInsertStatement insertStatement = new MySQLInsertStatement();
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(new ColumnSegment(0, 0, new IdentifierValue("IdentifierValue")));
+        AssignmentSegment assignment = new ColumnAssignmentSegment(0, 0, columnSegments, null);
         insertStatement.setSetAssignment(new SetAssignmentSegment(0, 0,
-                Collections.singleton(new AssignmentSegment(0, 0, new ColumnSegment(0, 0, new IdentifierValue("IdentifierValue")), null))));
+                Collections.singleton(assignment)));
         assertSQLStatementContextCreatedWhenSQLStatementInstanceOfInsertStatement(insertStatement);
     }
     
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/impl/InsertStatementContextTest.java b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/impl/InsertStatementContextTest.java
index 550ea0a..d52c994 100644
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/impl/InsertStatementContextTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/impl/InsertStatementContextTest.java
@@ -23,6 +23,7 @@ import org.apache.shardingsphere.infra.database.DefaultSchema;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -48,6 +49,7 @@ import org.junit.Test;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
 
@@ -159,10 +161,14 @@ public final class InsertStatementContextTest {
     }
     
     private void setUpOnDuplicateValues(final MySQLInsertStatement insertStatement) {
-        AssignmentSegment parameterMarkerExpressionAssignment = new AssignmentSegment(0, 0, 
-                new ColumnSegment(0, 0, new IdentifierValue("on_duplicate_key_update_column_1")), new ParameterMarkerExpressionSegment(0, 0, 4));
-        AssignmentSegment literalExpressionAssignment = new AssignmentSegment(0, 0, 
-                new ColumnSegment(0, 0, new IdentifierValue("on_duplicate_key_update_column_2")), new LiteralExpressionSegment(0, 0, 5));
+        List<ColumnSegment> parameterMarkerExpressionAssignmentColumns = new LinkedList<>();
+        parameterMarkerExpressionAssignmentColumns.add(new ColumnSegment(0, 0, new IdentifierValue("on_duplicate_key_update_column_1")));
+        AssignmentSegment parameterMarkerExpressionAssignment = new ColumnAssignmentSegment(0, 0, parameterMarkerExpressionAssignmentColumns, 
+                new ParameterMarkerExpressionSegment(0, 0, 4));
+        List<ColumnSegment> literalExpressionAssignmentColumns = new LinkedList<>();
+        literalExpressionAssignmentColumns.add(new ColumnSegment(0, 0, new IdentifierValue("on_duplicate_key_update_column_2")));
+        AssignmentSegment literalExpressionAssignment = new ColumnAssignmentSegment(0, 0, literalExpressionAssignmentColumns,
+                new LiteralExpressionSegment(0, 0, 5));
         OnDuplicateKeyColumnsSegment onDuplicateKeyColumnsSegment = new OnDuplicateKeyColumnsSegment(0, 0, Arrays.asList(parameterMarkerExpressionAssignment, literalExpressionAssignment));
         insertStatement.setOnDuplicateKeyColumns(onDuplicateKeyColumnsSegment);
     }
@@ -299,8 +305,10 @@ public final class InsertStatementContextTest {
     @Test
     public void assertGetValueListCountWithSetAssignmentForMySQL() {
         MySQLInsertStatement insertStatement = new MySQLInsertStatement();
-        insertStatement.setSetAssignment(new SetAssignmentSegment(0, 0, Collections.singletonList(new AssignmentSegment(0, 0,
-                new ColumnSegment(0, 0, new IdentifierValue("col")), new LiteralExpressionSegment(0, 0, 1)))));
+        List<ColumnSegment> columns = new LinkedList<>();
+        columns.add(new ColumnSegment(0, 0, new IdentifierValue("col")));
+        AssignmentSegment insertStatementAssignment = new ColumnAssignmentSegment(0, 0, columns, new LiteralExpressionSegment(0, 0, 1));
+        insertStatement.setSetAssignment(new SetAssignmentSegment(0, 0, Collections.singletonList(insertStatementAssignment)));
         insertStatement.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue(""))));
         InsertStatementContext insertStatementContext = createInsertStatementContext(Collections.emptyList(), insertStatement);
         assertThat(insertStatementContext.getValueListCount(), is(1));
@@ -344,8 +352,10 @@ public final class InsertStatementContextTest {
     @Test
     public void assertGetInsertColumnNamesForSetAssignmentForMySQL() {
         MySQLInsertStatement insertStatement = new MySQLInsertStatement();
-        insertStatement.setSetAssignment(new SetAssignmentSegment(0, 0, Collections.singletonList(new AssignmentSegment(0, 0,
-                new ColumnSegment(0, 0, new IdentifierValue("col")), new LiteralExpressionSegment(0, 0, 1)))));
+        List<ColumnSegment> columns = new LinkedList<>();
+        columns.add(new ColumnSegment(0, 0, new IdentifierValue("col")));
+        AssignmentSegment insertStatementAssignment = new ColumnAssignmentSegment(0, 0, columns, new LiteralExpressionSegment(0, 0, 1));
+        insertStatement.setSetAssignment(new SetAssignmentSegment(0, 0, Collections.singletonList(insertStatementAssignment)));
         insertStatement.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue(""))));
         InsertStatementContext insertStatementContext = createInsertStatementContext(Collections.emptyList(), insertStatement);
         List<String> columnNames = insertStatementContext.getInsertColumnNames();
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/impl/MySQLStatementSQLVisitor.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/impl/MySQLStatementSQLVisitor.java
index 8346fbd..267ccdd 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/impl/MySQLStatementSQLVisitor.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/impl/MySQLStatementSQLVisitor.java
@@ -127,6 +127,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.constant.UnionType;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -1094,7 +1095,10 @@ public abstract class MySQLStatementSQLVisitor extends MySQLStatementBaseVisitor
     public ASTNode visitAssignment(final AssignmentContext ctx) {
         ColumnSegment column = (ColumnSegment) visit(ctx.columnRef());
         ExpressionSegment value = (ExpressionSegment) visit(ctx.assignmentValue());
-        return new AssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), column, value);
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(column);
+        AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+        return result;
     }
     
     @Override
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/antlr4/imports/oracle/DMLStatement.g4 b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
index 78ff4da..4478ed1 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
@@ -90,19 +90,28 @@ collectionExpr
     ;
 
 update
-    : UPDATE updateSpecification? tableReferences setAssignmentsClause whereClause?
+    : UPDATE hint? updateSpecification alias? updateSetClause whereClause? returningClause? errorLoggingClause?
     ;
 
 updateSpecification
-    : ONLY
+    : dmlTableExprClause | (ONLY LP_ dmlTableExprClause RP_)
     ;
 
-assignment
-    : columnName EQ_ assignmentValue
+updateSetClause
+    : SET (updateSetColumnList | updateSetValueClause)
     ;
 
-setAssignmentsClause
-    : SET assignment (COMMA_ assignment)*
+updateSetColumnList
+    : updateSetColumnClause (COMMA_ updateSetColumnClause)*
+    ;
+
+updateSetColumnClause
+    : (LP_ columnName (COMMA_ columnName)* RP_ EQ_ LP_ selectSubquery RP_) 
+    | (columnName EQ_ (expr | LP_ selectSubquery RP_ | DEFAULT))
+    ;
+
+updateSetValueClause
+    : VALUE LP_ alias RP_ EQ_ (expr | LP_ selectSubquery RP_)
     ;
 
 assignmentValues
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
index 0f6e7d3..1675bee 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
@@ -24,7 +24,6 @@ import org.apache.shardingsphere.sql.parser.api.visitor.operation.SQLStatementVi
 import org.apache.shardingsphere.sql.parser.api.visitor.type.DMLSQLVisitor;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AliasContext;
-import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AssignmentContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AssignmentValueContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AssignmentValuesContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CellAssignmentContext;
@@ -87,7 +86,6 @@ import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Select
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectSubqueryContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectTableReferenceContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectUnionClauseContext;
-import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SetAssignmentsClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ShardsClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SingleColumnForLoopContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SubqueryContext;
@@ -96,11 +94,16 @@ import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableC
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableNameContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UnionClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSetClauseContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSetColumnClauseContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSetValueClauseContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSpecificationContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UsingClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.WhereClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.WithClauseContext;
 import org.apache.shardingsphere.sql.parser.sql.common.constant.OrderDirection;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -312,8 +315,11 @@ public final class OracleDMLStatementSQLVisitor extends OracleStatementSQLVisito
     @Override
     public ASTNode visitUpdate(final UpdateContext ctx) {
         OracleUpdateStatement result = new OracleUpdateStatement();
-        result.setTableSegment((TableSegment) visit(ctx.tableReferences()));
-        result.setSetAssignment((SetAssignmentSegment) visit(ctx.setAssignmentsClause()));
+        result.setTableSegment((TableSegment) visit(ctx.updateSpecification()));
+        if (null != ctx.alias()) {
+            result.getTableSegment().setAlias((AliasSegment) visit(ctx.alias()));
+        }
+        result.setSetAssignment((SetAssignmentSegment) visit(ctx.updateSetClause()));
         if (null != ctx.whereClause()) {
             result.setWhere((WhereSegment) visit(ctx.whereClause()));
         }
@@ -322,12 +328,95 @@ public final class OracleDMLStatementSQLVisitor extends OracleStatementSQLVisito
     }
     
     @Override
-    public ASTNode visitSetAssignmentsClause(final SetAssignmentsClauseContext ctx) {
+    public ASTNode visitUpdateSpecification(final UpdateSpecificationContext ctx) {
+        TableSegment result;
+        if (null != ctx.dmlTableExprClause().dmlTableClause()) {
+            result = (TableSegment) visit(ctx.dmlTableExprClause().dmlTableClause());
+        } else if (null != ctx.dmlTableExprClause().dmlSubqueryClause()) {
+            SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.dmlTableExprClause().dmlSubqueryClause());
+            SubqueryTableSegment subqueryTableSegment = new SubqueryTableSegment(subquerySegment);
+            result = (TableSegment) subqueryTableSegment;
+        } else {
+            SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.dmlTableExprClause().tableCollectionExpr());
+            SubqueryTableSegment subqueryTableSegment = new SubqueryTableSegment(subquerySegment);
+            result = (TableSegment) subqueryTableSegment;
+        }
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitUpdateSetClause(final UpdateSetClauseContext ctx) {
         Collection<AssignmentSegment> assignments = new LinkedList<>();
-        for (AssignmentContext each : ctx.assignment()) {
-            assignments.add((AssignmentSegment) visit(each));
+        if (null != ctx.updateSetColumnList()) {
+            for (UpdateSetColumnClauseContext each : ctx.updateSetColumnList().updateSetColumnClause()) {
+                assignments.add((AssignmentSegment) visit(each));
+            }
+        } else {
+            assignments.add((AssignmentSegment) visit(ctx.updateSetValueClause()));
+        }
+        SetAssignmentSegment result = new SetAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), assignments);
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitUpdateSetColumnClause(final UpdateSetColumnClauseContext ctx) {
+        AssignmentSegment result = 1 == ctx.columnName().size() ? createAssignmentSegmentFromSingleColumnAssignment(ctx) : createAssignmentSegmentFromMultiColumnAssignment(ctx);
+        return result;
+    }
+    
+    private AssignmentSegment createAssignmentSegmentFromSingleColumnAssignment(final UpdateSetColumnClauseContext ctx) {
+        ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName(0));
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(column);
+        if (null != ctx.expr()) {
+            ExpressionSegment value = (ExpressionSegment) visit(ctx.expr());
+            AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+            return result;
+        } else if (null != ctx.selectSubquery()) {
+            SubquerySegment subquerySegment =
+                    new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), (OracleSelectStatement) visit(ctx.selectSubquery()));
+            SubqueryExpressionSegment value = new SubqueryExpressionSegment(subquerySegment);
+            AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+            result.getColumns().add(column);
+            return result;
+        } else {
+            CommonExpressionSegment value = new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.DEFAULT().getText());
+            AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+            result.getColumns().add(column);
+            return result;
+        }
+    }
+    
+    private AssignmentSegment createAssignmentSegmentFromMultiColumnAssignment(final UpdateSetColumnClauseContext ctx) {
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        for (ColumnNameContext each : ctx.columnName()) {
+            columnSegments.add((ColumnSegment) visit(each));
+        }
+        SubquerySegment subquerySegment =
+                new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), (OracleSelectStatement) visit(ctx.selectSubquery()));
+        SubqueryExpressionSegment value = new SubqueryExpressionSegment(subquerySegment);
+        AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitUpdateSetValueClause(final UpdateSetValueClauseContext ctx) {
+        ColumnSegment column = new ColumnSegment(ctx.alias().start.getStartIndex(), ctx.alias().stop.getStopIndex(), (IdentifierValue) visit(ctx.alias().identifier()));
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(column);
+        if (null != ctx.expr()) {
+            ExpressionSegment value = (ExpressionSegment) visit(ctx.expr());
+            AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+            result.getColumns().add(column);
+            return result;
+        } else {
+            SubquerySegment subquerySegment =
+                    new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), (OracleSelectStatement) visit(ctx.selectSubquery()));
+            SubqueryExpressionSegment value = new SubqueryExpressionSegment(subquerySegment);
+            AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+            result.getColumns().add(column);
+            return result;   
         }
-        return new SetAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), assignments);
     }
     
     @Override
@@ -340,13 +429,6 @@ public final class OracleDMLStatementSQLVisitor extends OracleStatementSQLVisito
     }
     
     @Override
-    public ASTNode visitAssignment(final AssignmentContext ctx) {
-        ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName());
-        ExpressionSegment value = (ExpressionSegment) visit(ctx.assignmentValue());
-        return new AssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), column, value);
-    }
-    
-    @Override
     public ASTNode visitAssignmentValue(final AssignmentValueContext ctx) {
         ExprContext expr = ctx.expr();
         if (null != expr) {
@@ -1036,7 +1118,10 @@ public final class OracleDMLStatementSQLVisitor extends OracleStatementSQLVisito
     public ASTNode visitMergeAssignment(final MergeAssignmentContext ctx) {
         ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName());
         ExpressionSegment value = (ExpressionSegment) visit(ctx.mergeAssignmentValue());
-        return new AssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), column, value);
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(column);
+        AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+        return result;
     }
     
     @Override
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java
index 6bbb920..0f5c040 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java
@@ -101,6 +101,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.constant.OrderDirection;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -651,8 +652,11 @@ public abstract class PostgreSQLStatementSQLVisitor extends PostgreSQLStatementB
     @Override
     public ASTNode visitSetClause(final SetClauseContext ctx) {
         ColumnSegment columnSegment = (ColumnSegment) visit(ctx.setTarget());
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(columnSegment);
         ExpressionSegment expressionSegment = (ExpressionSegment) visit(ctx.aExpr());
-        return new AssignmentSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), columnSegment, expressionSegment);
+        AssignmentSegment result = new ColumnAssignmentSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), columnSegments, expressionSegment);
+        return result;
     }
     
     @Override
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sql92/src/main/java/org/apache/shardingsphere/sql/parser/sql92/visitor/statement/impl/SQL92DMLStatementSQLVisitor.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sql92/src/main/java/org/apache/shardingsphere/sql/parser/sql92/visitor/statement/impl/SQL92DMLStatementSQLVisitor.java
index b34b770..d9b8f6f 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sql92/src/main/java/org/apache/shardingsphere/sql/parser/sql92/visitor/statement/impl/SQL92DMLStatementSQLVisitor.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sql92/src/main/java/org/apache/shardingsphere/sql/parser/sql92/visitor/statement/impl/SQL92DMLStatementSQLVisitor.java
@@ -56,6 +56,7 @@ import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.UnionCl
 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.UpdateContext;
 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.WhereClauseContext;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -172,8 +173,12 @@ public final class SQL92DMLStatementSQLVisitor extends SQL92StatementSQLVisitor
     @Override
     public ASTNode visitAssignment(final AssignmentContext ctx) {
         ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName());
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(column);
         ExpressionSegment value = (ExpressionSegment) visit(ctx.assignmentValue());
-        return new AssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), column, value);
+        AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+        result.getColumns().add(column);
+        return result;
     }
     
     @Override
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/impl/SQLServerDMLStatementSQLVisitor.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/impl/SQLServerDMLStatementSQLVisitor.java
index 4706647..2d3d87d 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/impl/SQLServerDMLStatementSQLVisitor.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/impl/SQLServerDMLStatementSQLVisitor.java
@@ -67,6 +67,7 @@ import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.Upd
 import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WhereClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WithClauseContext;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -293,8 +294,12 @@ public final class SQLServerDMLStatementSQLVisitor extends SQLServerStatementSQL
     @Override
     public ASTNode visitAssignment(final AssignmentContext ctx) {
         ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName());
+        List<ColumnSegment> columnSegments = new LinkedList<>();
+        columnSegments.add(column);
         ExpressionSegment value = (ExpressionSegment) visit(ctx.assignmentValue());
-        return new AssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), column, value);
+        AssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
+        result.getColumns().add(column);
+        return result;
     }
     
     @Override
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/extractor/TableExtractor.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/extractor/TableExtractor.java
index 1743bb7..0a37604 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/extractor/TableExtractor.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/extractor/TableExtractor.java
@@ -238,7 +238,7 @@ public final class TableExtractor {
      */
     public void extractTablesFromUpdate(final UpdateStatement updateStatement) {
         extractTablesFromTableSegment(updateStatement.getTableSegment());
-        updateStatement.getSetAssignment().getAssignments().forEach(each -> extractTablesFromExpression(each.getColumn()));
+        updateStatement.getSetAssignment().getAssignments().forEach(each -> extractTablesFromExpression(each.getColumns().get(0)));
         if (updateStatement.getWhere().isPresent()) {
             extractTablesFromExpression(updateStatement.getWhere().get().getExpr());
         }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/AssignmentSegment.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/AssignmentSegment.java
index 211c029..6d2f1c3 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/AssignmentSegment.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/AssignmentSegment.java
@@ -17,24 +17,28 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment;
 
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
 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.SQLSegment;
+
+import java.util.List;
 
 /**
  * Assignment segment.
  */
-@RequiredArgsConstructor
-@Getter
-public final class AssignmentSegment implements SQLSegment {
-    
-    private final int startIndex;
-    
-    private final int stopIndex;
+public abstract class AssignmentSegment implements SQLSegment {
     
-    private final ColumnSegment column;
+    /**
+     * Get list of column segments.
+     * 
+     * @return list of ColumnSegment
+     */
+    public abstract List<ColumnSegment> getColumns();
     
-    private final ExpressionSegment value;
+    /**
+     * Get expression segment value.
+     * 
+     * @return ExpressionSegment
+     */
+    public abstract ExpressionSegment getValue();
 }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/AssignmentSegment.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/ColumnAssignmentSegment.java
similarity index 86%
copy from shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/AssignmentSegment.java
copy to shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/ColumnAssignmentSegment.java
index 211c029..1e3dab1 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/AssignmentSegment.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/assignment/ColumnAssignmentSegment.java
@@ -21,20 +21,21 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 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.SQLSegment;
+
+import java.util.List;
 
 /**
- * Assignment segment.
+ * Column Assignment segment.
  */
 @RequiredArgsConstructor
 @Getter
-public final class AssignmentSegment implements SQLSegment {
+public final class ColumnAssignmentSegment extends AssignmentSegment {
     
     private final int startIndex;
     
     private final int stopIndex;
     
-    private final ColumnSegment column;
+    private final List<ColumnSegment> columns;
     
     private final ExpressionSegment value;
 }
diff --git a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentAssert.java b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentAssert.java
index 51836c2..43467d9 100644
--- a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentAssert.java
+++ b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentAssert.java
@@ -19,11 +19,15 @@ package org.apache.shardingsphere.test.sql.parser.parameterized.asserts.segment.
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.SQLCaseAssertContext;
 import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.segment.column.ColumnAssert;
 import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.assignment.ExpectedAssignment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
 /**
  * Assignment assert.
  */
@@ -38,8 +42,19 @@ public final class AssignmentAssert {
      * @param expected expected assignment
      */
     public static void assertIs(final SQLCaseAssertContext assertContext, final AssignmentSegment actual, final ExpectedAssignment expected) {
-        ColumnAssert.assertIs(assertContext, actual.getColumn(), expected.getColumn());
-        // TODO assert assign operator
-        AssignmentValueAssert.assertIs(assertContext, actual.getValue(), expected.getAssignmentValue());
+        if (null != expected.getColumns()) {
+            assertThat(assertContext.getText("Assignment columns size assertion error: "), actual.getColumns().size(), is(expected.getColumns().size()));
+            int count = 0;
+            for (ColumnSegment each : actual.getColumns()) {
+                ColumnAssert.assertIs(assertContext, each, expected.getColumns().get(count));
+                count++;
+            }
+            // TODO assert assign operator
+            AssignmentValueAssert.assertIs(assertContext, actual.getValue(), expected.getAssignmentValue());
+        } else {
+            ColumnAssert.assertIs(assertContext, actual.getColumns().get(0), expected.getColumn());
+            // TODO assert assign operator
+            AssignmentValueAssert.assertIs(assertContext, actual.getValue(), expected.getAssignmentValue());   
+        }
     }
 }
diff --git a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentValueAssert.java b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentValueAssert.java
index c682698..ab0c1a5 100644
--- a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentValueAssert.java
+++ b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/asserts/segment/assignment/AssignmentValueAssert.java
@@ -23,6 +23,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.Column
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 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;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
 import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.SQLCaseAssertContext;
 import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.segment.column.ColumnAssert;
@@ -52,6 +53,8 @@ public final class AssignmentValueAssert {
             ExpressionAssert.assertCommonExpression(assertContext, (ExpressionProjectionSegment) actual, expected.getCommonExpression());
         } else if (actual instanceof ColumnSegment) {
             ColumnAssert.assertIs(assertContext, (ColumnSegment) actual, expected.getColumn());
+        } else if (actual instanceof SubqueryExpressionSegment) {
+            ExpressionAssert.assertSubqueryExpression(assertContext, (SubqueryExpressionSegment) actual, expected.getSubquery());
         }
     }
 }
diff --git a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignment.java b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignment.java
index 580f073..9b65f88 100644
--- a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignment.java
+++ b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignment.java
@@ -23,6 +23,7 @@ import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain
 import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.column.ExpectedColumn;
 
 import javax.xml.bind.annotation.XmlElement;
+import java.util.List;
 
 /**
  * Expected assignment.
@@ -34,6 +35,9 @@ public final class ExpectedAssignment extends AbstractExpectedSQLSegment {
     @XmlElement
     private ExpectedColumn column;
     
+    @XmlElement(name = "columns")
+    private List<ExpectedColumn> columns;
+    
     @XmlElement(name = "assignment-value")
     private ExpectedAssignmentValue assignmentValue;
 }
diff --git a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignmentValue.java b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignmentValue.java
index 6eba0750..0e2ab58 100644
--- a/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignmentValue.java
+++ b/shardingsphere-test/shardingsphere-parser-test/src/main/java/org/apache/shardingsphere/test/sql/parser/parameterized/jaxb/cases/domain/segment/impl/assignment/ExpectedAssignmentValue.java
@@ -24,6 +24,7 @@ import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain
 import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.expr.complex.ExpectedCommonExpression;
 import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.expr.simple.ExpectedLiteralExpression;
 import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.expr.simple.ExpectedParameterMarkerExpression;
+import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.expr.simple.ExpectedSubquery;
 
 import javax.xml.bind.annotation.XmlElement;
 
@@ -45,4 +46,7 @@ public final class ExpectedAssignmentValue extends AbstractExpectedSQLSegment {
     
     @XmlElement(name = "column")
     private ExpectedColumn column;
+    
+    @XmlElement(name = "subquery")
+    private ExpectedSubquery subquery;
 }
diff --git a/shardingsphere-test/shardingsphere-parser-test/src/main/resources/case/dml/update.xml b/shardingsphere-test/shardingsphere-parser-test/src/main/resources/case/dml/update.xml
index c999e36..82d3a24 100644
--- a/shardingsphere-test/shardingsphere-parser-test/src/main/resources/case/dml/update.xml
+++ b/shardingsphere-test/shardingsphere-parser-test/src/main/resources/case/dml/update.xml
@@ -302,52 +302,6 @@
         </where>
     </update>
 
-    <update sql-case-id="update_with_special_comments" parameters="'update', 1, 1">
-        <table start-index="33" stop-index="39">
-            <simple-table name="t_order" start-index="33" stop-index="39"/>
-        </table>
-        <set start-index="41" stop-index="52" literal-stop-index="59">
-            <assignment start-index="45" stop-index="52" literal-stop-index="59">
-                <column name="status" start-index="45" stop-index="50" />
-                <assignment-value>
-                    <parameter-marker-expression value="0" start-index="52" stop-index="52" />
-                    <literal-expression value="update" start-index="52" stop-index="59" />
-                </assignment-value>
-            </assignment>
-        </set>
-        <where start-index="54" stop-index="87" literal-start-index="61" literal-stop-index="94">
-            <expr>
-                <binary-operation-expression start-index="60" stop-index="87" literal-start-index="67" literal-stop-index="94">
-                    <left>
-                        <binary-operation-expression start-index="60" stop-index="71" literal-start-index="67" literal-stop-index="78">
-                            <left>
-                                <column name="order_id" start-index="60" stop-index="67" literal-start-index="67" literal-stop-index="74" />
-                            </left>
-                            <operator>=</operator>
-                            <right>
-                                <literal-expression value="1" start-index="78" stop-index="78" />
-                                <parameter-marker-expression value="1" start-index="71" stop-index="71" />
-                            </right>
-                        </binary-operation-expression>
-                    </left>
-                    <operator>AND</operator>
-                    <right>
-                        <binary-operation-expression start-index="77" stop-index="87" literal-start-index="84" literal-stop-index="94">
-                            <left>
-                                <column name="user_id" start-index="77" stop-index="83" literal-start-index="84" literal-stop-index="90" />
-                            </left>
-                            <operator>=</operator>
-                            <right>
-                                <literal-expression value="1" start-index="94" stop-index="94" />
-                                <parameter-marker-expression value="2" start-index="87" stop-index="87" />
-                            </right>
-                        </binary-operation-expression>
-                    </right>
-                </binary-operation-expression>
-            </expr>
-        </where>
-    </update>
-
     <update sql-case-id="update_without_parameters">
         <table start-index="7" stop-index="13">
             <simple-table name="t_order" start-index="7" stop-index="13"/>
@@ -863,4 +817,231 @@
             </expr>
         </where>
     </update>
+
+    <update sql-case-id="update_with_set_null">
+        <table start-index="7" stop-index="13">
+            <simple-table name="employees" start-index="7" stop-index="15"/>
+        </table>
+        <set start-index="17" stop-index="41">
+            <assignment start-index="21" stop-index="41">
+                <column name="commission_pct" start-index="21" stop-index="34" />
+                <assignment-value>
+                    <literal-expression value="NULL" start-index="38" stop-index="41" />
+                </assignment-value>
+            </assignment>
+        </set>
+        <where start-index="43" stop-index="67">
+            <expr>
+                <binary-operation-expression start-index="49" stop-index="67">
+                    <left>
+                        <column name="job_id" start-index="49" stop-index="54" />
+                    </left>
+                    <operator>=</operator>
+                    <right>
+                        <literal-expression value="SH_CLERK" start-index="58" stop-index="67" />
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </where>
+    </update>
+
+    <update sql-case-id="update_with_set_subquery">
+        <table start-index="7" stop-index="17">
+            <simple-table name="employees" alias="a" start-index="7" stop-index="17"/>
+        </table>
+        <set start-index="19" stop-index="104">
+            <assignment start-index="23" stop-index="104">
+                <column name="department_id" start-index="23" stop-index="35" />
+                <assignment-value>
+                    <subquery start-index="39" stop-index="104">
+                        <select>
+                            <from start-index="66" stop-index="76">
+                                <simple-table name="departments" start-index="66" stop-index="76"/>
+                            </from>
+                            <projections start-index="47" stop-index="59">
+                                <column-projection name="department_id" start-index="47" stop-index="59"/>
+                            </projections>
+                            <where start-index="78" stop-index="103">
+                                <expr>
+                                    <binary-operation-expression start-index="84" stop-index="103">
+                                        <left>
+                                            <column name="location_id" start-index="84" stop-index="94"/>
+                                        </left>
+                                        <operator>=</operator>
+                                        <right>
+                                            <literal-expression value="2100" start-index="98" stop-index="103"/>
+                                        </right>
+                                    </binary-operation-expression>
+                                </expr>
+                            </where>
+                        </select>
+                    </subquery>
+                </assignment-value>
+            </assignment>
+        </set>
+    </update>
+
+    <update sql-case-id="update_with_multiple_set">
+        <table start-index="7" stop-index="15">
+            <simple-table name="employees" start-index="7" stop-index="15"/>
+        </table>
+        <set start-index="17" stop-index="73">
+            <assignment start-index="21" stop-index="37">
+                <column name="job_id" start-index="21" stop-index="26" />
+                <assignment-value>
+                    <literal-expression value="SA_MAN" start-index="30" stop-index="37" />
+                </assignment-value>
+            </assignment>
+            <assignment start-index="40" stop-index="61">
+                <column name="salary" start-index="40" stop-index="45" />
+                <assignment-value>
+                    <literal-expression value="1000" start-index="49" stop-index="52" />
+                </assignment-value>
+            </assignment>
+            <assignment start-index="64" stop-index="82">
+                <column name="department_id" start-index="55" stop-index="67" />
+                <assignment-value>
+                    <literal-expression value="120" start-index="71" stop-index="73" />
+                </assignment-value>
+            </assignment>
+        </set>
+        <where start-index="75" stop-index="107">
+            <expr>
+                <binary-operation-expression start-index="81" stop-index="107">
+                    <left>
+                        <column name="last_name" start-index="81" stop-index="89" />
+                    </left>
+                    <operator>=</operator>
+                    <right>
+                        <literal-expression value="Douglas Grant" start-index="93" stop-index="107" />
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </where>
+    </update>
+
+    <update sql-case-id="update_with_set_value">
+        <table start-index="7" stop-index="20">
+            <simple-table name="people_demo1" alias="p" start-index="7" stop-index="20"/>
+        </table>
+        <set start-index="22" stop-index="113">
+            <assignment start-index="26" stop-index="113">
+                <column name="p" start-index="32" stop-index="32" />
+                <assignment-value>
+                    <subquery start-index="37" stop-index="113">
+                        <select>
+                            <from start-index="59" stop-index="72">
+                                <simple-table name="people_demo2" alias="q" start-index="59" stop-index="72"/>
+                            </from>
+                            <projections start-index="45" stop-index="52">
+                                <expression-projection text="VALUE(q)" start-index="45" stop-index="52"/>
+                            </projections>
+                            <where start-index="74" stop-index="112">
+                                <expr>
+                                    <binary-operation-expression start-index="80" stop-index="112">
+                                        <left>
+                                            <column name="department_id" start-index="80" stop-index="94">
+                                                <owner name="p" start-index="80" stop-index="80"/>
+                                            </column>
+                                        </left>
+                                        <operator>=</operator>
+                                        <right>
+                                            <column name="department_id" start-index="98" stop-index="112">
+                                                <owner name="q" start-index="98" stop-index="98"/>
+                                            </column>
+                                        </right>
+                                    </binary-operation-expression>
+                                </expr>
+                            </where>
+                        </select>
+                    </subquery>
+                </assignment-value>
+            </assignment>
+        </set>
+        <where start-index="115" stop-index="140">
+            <expr>
+                <binary-operation-expression start-index="121" stop-index="140">
+                    <left>
+                        <column name="department_id" start-index="121" stop-index="135">
+                            <owner name="p" start-index="121" stop-index="121"/>
+                        </column>
+                    </left>
+                    <operator>=</operator>
+                    <right>
+                        <literal-expression value="10" start-index="139" stop-index="140" />
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </where>
+    </update>
+
+    <update sql-case-id="update_with_multi_columns">
+        <table start-index="7" stop-index="17">
+            <simple-table name="employees" alias="a" start-index="7" stop-index="17"/>
+        </table>
+        <set start-index="19" stop-index="239">
+            <assignment start-index="23" stop-index="104">
+                <column name="department_id" start-index="23" stop-index="35" />
+                <assignment-value>
+                    <subquery start-index="39" stop-index="104">
+                        <select>
+                            <from start-index="66" stop-index="76">
+                                <simple-table name="departments" start-index="66" stop-index="76"/>
+                            </from>
+                            <projections start-index="47" stop-index="59">
+                                <column-projection name="department_id" start-index="47" stop-index="59"/>
+                            </projections>
+                            <where start-index="78" stop-index="103">
+                                <expr>
+                                    <binary-operation-expression start-index="84" stop-index="103">
+                                        <left>
+                                            <column name="location_id" start-index="84" stop-index="94"/>
+                                        </left>
+                                        <operator>=</operator>
+                                        <right>
+                                            <literal-expression value="2100" start-index="98" stop-index="103"/>
+                                        </right>
+                                    </binary-operation-expression>
+                                </expr>
+                            </where>
+                        </select>
+                    </subquery>
+                </assignment-value>
+            </assignment>
+            <assignment start-index="107" stop-index="239">
+                <columns name="salary" start-index="108" stop-index="113"/>
+                <columns name="commission_pct" start-index="116" stop-index="129"/>
+                <assignment-value>
+                    <subquery start-index="135" stop-index="238">
+                        <select>
+                            <from start-index="188" stop-index="198">
+                                <simple-table name="employees" alias="b" start-index="188" stop-index="198"/>
+                            </from>
+                            <projections start-index="142" stop-index="181">
+                                <expression-projection text="1.1*AVG(salary)" start-index="142" stop-index="156"/>
+                                <expression-projection text="1.5*AVG(commission_pct)" start-index="159" stop-index="181"/>
+                            </projections>
+                            <where start-index="200" stop-index="238">
+                                <expr>
+                                    <binary-operation-expression start-index="206" stop-index="238">
+                                        <left>
+                                            <column name="department_id" start-index="206" stop-index="220">
+                                                <owner name="a" start-index="206" stop-index="206" />
+                                            </column>
+                                        </left>
+                                        <operator>=</operator>
+                                        <right>
+                                            <column name="department_id" start-index="224" stop-index="238">
+                                                <owner name="b" start-index="224" stop-index="224" />
+                                            </column>
+                                        </right>
+                                    </binary-operation-expression>
+                                </expr>
+                            </where>
+                        </select>
+                    </subquery>
+                </assignment-value>
+            </assignment>
+        </set>
+    </update>
 </sql-parser-test-cases>
diff --git a/shardingsphere-test/shardingsphere-parser-test/src/main/resources/sql/supported/dml/update.xml b/shardingsphere-test/shardingsphere-parser-test/src/main/resources/sql/supported/dml/update.xml
index 0c21f57..2ddc0a4 100644
--- a/shardingsphere-test/shardingsphere-parser-test/src/main/resources/sql/supported/dml/update.xml
+++ b/shardingsphere-test/shardingsphere-parser-test/src/main/resources/sql/supported/dml/update.xml
@@ -23,7 +23,6 @@
     <sql-case id="update_without_condition" value="UPDATE t_order o SET o.status = 'finished'" db-types="MySQL,H2" />
     <sql-case id="update_with_extra_keywords" value="UPDATE LOW_PRIORITY IGNORE t_order SET status = ? WHERE order_id = ? AND user_id = ?" db-types="MySQL" />
     <sql-case id="update_with_special_character" value="UPDATE `t_order` SET `status` = ? WHERE `order_id` = ? AND user_id = ?" db-types="MySQL" />
-    <sql-case id="update_with_special_comments" value="UPDATE /*+ index(field1) */ ONLY t_order SET status=? WHERE order_id = ? AND user_id = ? RETURN * LOG ERRORS INTO TABLE_LOG" db-types="Oracle" />
     <sql-case id="update_without_parameters" value="UPDATE t_order SET status = 'update' WHERE order_id = 1000 AND user_id = 10" />
     <sql-case id="update_with_or" value="UPDATE t_order SET status = 'update' WHERE (order_id = ? OR order_id = ?) AND user_id = ?" />
     <sql-case id="update_with_set_calculation" value="UPDATE t_order SET status = status - ? WHERE order_id = ? AND user_id = ?" />
@@ -37,4 +36,9 @@
     <sql-case id="update_with_top" value="UPDATE TOP(10) t_order SET order_id = ? WHERE user_id = ?" db-types="SQLServer" />
     <sql-case id="update_with_top_percent" value="UPDATE TOP(10) PERCENT t_order SET order_id = ? WHERE user_id = ?" db-types="SQLServer" />
     <sql-case id="update_with_query_hint" value="UPDATE t_order SET status = ? WHERE order_id = ? HASH GROUP" db-types="SQLServer" />
+    <sql-case id="update_with_set_null" value="UPDATE employees SET commission_pct = NULL WHERE job_id = 'SH_CLERK'" db-types="Oracle" />
+    <sql-case id="update_with_set_subquery" value="UPDATE employees a SET department_id = (SELECT department_id FROM departments WHERE location_id = '2100')" db-types="Oracle" />
+    <sql-case id="update_with_multiple_set" value="UPDATE employees SET job_id = 'SA_MAN', salary = 1000, department_id = 120 WHERE last_name = 'Douglas Grant'" db-types="Oracle" />
+    <sql-case id="update_with_set_value" value="UPDATE people_demo1 p SET VALUE(p) = (SELECT VALUE(q) FROM people_demo2 q WHERE p.department_id = q.department_id) WHERE p.department_id = 10" db-types="Oracle" />
+    <sql-case id="update_with_multi_columns" value="UPDATE employees a SET department_id = (SELECT department_id FROM departments WHERE location_id = '2100'), (salary, commission_pct) = (SELECT 1.1*AVG(salary), 1.5*AVG(commission_pct) FROM employees b WHERE a.department_id = b.department_id)" db-types="Oracle" />
 </sql-cases>