<h2 dir="auto">Feature Request</h2>
<p dir="auto">Now, when a user executes an <code class="notranslate">insert into on duplicate key update</code> statement on a sharding key, an exception will be thrown.</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="/**
 * Sharding insert statement validator.
 */
@RequiredArgsConstructor
public final class ShardingInsertStatementValidator extends ShardingDMLStatementValidator&lt;InsertStatement&gt; {
    
    private final ShardingConditions shardingConditions;
    
    @Override
    public void preValidate(final ShardingRule shardingRule, final SQLStatementContext&lt;InsertStatement&gt; sqlStatementContext,
                            final List&lt;Object&gt; parameters, final ShardingSphereSchema schema) {
        if (null == ((InsertStatementContext) sqlStatementContext).getInsertSelectContext()) {
            validateMultipleTable(shardingRule, sqlStatementContext);
        }
        InsertStatement sqlStatement = sqlStatementContext.getSqlStatement();
        Optional&lt;OnDuplicateKeyColumnsSegment&gt; onDuplicateKeyColumnsSegment = InsertStatementHandler.getOnDuplicateKeyColumnsSegment(sqlStatement);
        String tableName = sqlStatement.getTable().getTableName().getIdentifier().getValue();
        if (onDuplicateKeyColumnsSegment.isPresent() &amp;&amp; isUpdateShardingKey(shardingRule, onDuplicateKeyColumnsSegment.get(), tableName)) {
            throw new ShardingSphereException(&quot;INSERT INTO ... ON DUPLICATE KEY UPDATE can not support update for sharding column.&quot;);
        }
        Optional&lt;SubquerySegment&gt; insertSelectSegment = sqlStatement.getInsertSelect();
        if (insertSelectSegment.isPresent() &amp;&amp; isContainsKeyGenerateStrategy(shardingRule, tableName)
                &amp;&amp; !isContainsKeyGenerateColumn(shardingRule, sqlStatement.getColumns(), tableName)) {
            throw new ShardingSphereException(&quot;INSERT INTO ... SELECT can not support applying keyGenerator to absent generateKeyColumn.&quot;);
        }
        TablesContext tablesContext = sqlStatementContext.getTablesContext();
        if (insertSelectSegment.isPresent() &amp;&amp; !isAllSameTables(tablesContext.getTableNames()) &amp;&amp; !shardingRule.isAllBindingTables(tablesContext.getTableNames())) {
            throw new ShardingSphereException(&quot;The table inserted and the table selected must be the same or bind tables.&quot;);
        }
    }"><pre class="notranslate"><span class="pl-c">/**</span>
<span class="pl-c"> * Sharding insert statement validator.</span>
<span class="pl-c"> */</span>
<span class="pl-c1">@</span><span class="pl-c1">RequiredArgsConstructor</span>
<span class="pl-k">public</span> <span class="pl-k">final</span> <span class="pl-k">class</span> <span class="pl-smi">ShardingInsertStatementValidator</span> <span class="pl-k">extends</span> <span class="pl-smi">ShardingDMLStatementValidator</span>&lt;<span class="pl-smi">InsertStatement</span>&gt; {
    
    <span class="pl-k">private</span> <span class="pl-k">final</span> <span class="pl-smi">ShardingConditions</span> <span class="pl-s1">shardingConditions</span>;
    
    <span class="pl-c1">@</span><span class="pl-c1">Override</span>
    <span class="pl-k">public</span> <span class="pl-smi">void</span> <span class="pl-en">preValidate</span>(<span class="pl-k">final</span> <span class="pl-smi">ShardingRule</span> <span class="pl-s1">shardingRule</span>, <span class="pl-k">final</span> <span class="pl-smi">SQLStatementContext</span>&lt;<span class="pl-smi">InsertStatement</span>&gt; <span class="pl-s1">sqlStatementContext</span>,
                            <span class="pl-k">final</span> <span class="pl-smi">List</span>&lt;<span class="pl-smi">Object</span>&gt; <span class="pl-s1">parameters</span>, <span class="pl-k">final</span> <span class="pl-smi">ShardingSphereSchema</span> <span class="pl-s1">schema</span>) {
        <span class="pl-k">if</span> (<span class="pl-c1">null</span> == ((<span class="pl-smi">InsertStatementContext</span>) <span class="pl-s1">sqlStatementContext</span>).<span class="pl-en">getInsertSelectContext</span>()) {
            <span class="pl-en">validateMultipleTable</span>(<span class="pl-s1">shardingRule</span>, <span class="pl-s1">sqlStatementContext</span>);
        }
        <span class="pl-smi">InsertStatement</span> <span class="pl-s1">sqlStatement</span> = <span class="pl-s1">sqlStatementContext</span>.<span class="pl-en">getSqlStatement</span>();
        <span class="pl-smi">Optional</span>&lt;<span class="pl-smi">OnDuplicateKeyColumnsSegment</span>&gt; <span class="pl-s1">onDuplicateKeyColumnsSegment</span> = <span class="pl-smi">InsertStatementHandler</span>.<span class="pl-en">getOnDuplicateKeyColumnsSegment</span>(<span class="pl-s1">sqlStatement</span>);
        <span class="pl-smi">String</span> <span class="pl-s1">tableName</span> = <span class="pl-s1">sqlStatement</span>.<span class="pl-en">getTable</span>().<span class="pl-en">getTableName</span>().<span class="pl-en">getIdentifier</span>().<span class="pl-en">getValue</span>();
        <span class="pl-k">if</span> (<span class="pl-s1">onDuplicateKeyColumnsSegment</span>.<span class="pl-en">isPresent</span>() &amp;&amp; <span class="pl-en">isUpdateShardingKey</span>(<span class="pl-s1">shardingRule</span>, <span class="pl-s1">onDuplicateKeyColumnsSegment</span>.<span class="pl-en">get</span>(), <span class="pl-s1">tableName</span>)) {
            <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">ShardingSphereException</span>(<span class="pl-s">"INSERT INTO ... ON DUPLICATE KEY UPDATE can not support update for sharding column."</span>);
        }
        <span class="pl-smi">Optional</span>&lt;<span class="pl-smi">SubquerySegment</span>&gt; <span class="pl-s1">insertSelectSegment</span> = <span class="pl-s1">sqlStatement</span>.<span class="pl-en">getInsertSelect</span>();
        <span class="pl-k">if</span> (<span class="pl-s1">insertSelectSegment</span>.<span class="pl-en">isPresent</span>() &amp;&amp; <span class="pl-en">isContainsKeyGenerateStrategy</span>(<span class="pl-s1">shardingRule</span>, <span class="pl-s1">tableName</span>)
                &amp;&amp; !<span class="pl-en">isContainsKeyGenerateColumn</span>(<span class="pl-s1">shardingRule</span>, <span class="pl-s1">sqlStatement</span>.<span class="pl-en">getColumns</span>(), <span class="pl-s1">tableName</span>)) {
            <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">ShardingSphereException</span>(<span class="pl-s">"INSERT INTO ... SELECT can not support applying keyGenerator to absent generateKeyColumn."</span>);
        }
        <span class="pl-smi">TablesContext</span> <span class="pl-s1">tablesContext</span> = <span class="pl-s1">sqlStatementContext</span>.<span class="pl-en">getTablesContext</span>();
        <span class="pl-k">if</span> (<span class="pl-s1">insertSelectSegment</span>.<span class="pl-en">isPresent</span>() &amp;&amp; !<span class="pl-en">isAllSameTables</span>(<span class="pl-s1">tablesContext</span>.<span class="pl-en">getTableNames</span>()) &amp;&amp; !<span class="pl-s1">shardingRule</span>.<span class="pl-en">isAllBindingTables</span>(<span class="pl-s1">tablesContext</span>.<span class="pl-en">getTableNames</span>())) {
            <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">ShardingSphereException</span>(<span class="pl-s">"The table inserted and the table selected must be the same or bind tables."</span>);
        }
    }</pre></div>
<p dir="auto">But if the routing results before and after the update have not changed, then we should support this type of <code class="notranslate">insert into on duplicate key update</code> statement.</p>
<h3 dir="auto">Is your feature request related to a problem?</h3>
<p dir="auto">No</p>
<h3 dir="auto">Describe the feature you would like.</h3>
<p dir="auto">Please answer these questions before submitting your issue. Thanks!</p>
<h3 dir="auto">Which version of Sharding-Jdbc do you using?</h3>
<p dir="auto">2.0.0 使用 java config 配置数据源</p>
<h3 dir="auto">Expected behavior</h3>
<p dir="auto">表 IM_TEST 分为2库TEST_00 TEST_01，每库5表，分库 id%2，分表 id%5<br>
select * from IM_TEST where id in(4,5)<br>
期望路由到TEST_00.IM_TEST_04 和 TEST_01.TEST_00</p>
<h3 dir="auto">Actual behavior</h3>
<p dir="auto">实际路由到了TEST_00.IM_TEST_04 和 TEST_00.TEST_00 TEST_01.IM_TEST_04 和 TEST_01.TEST_00</p>
<h3 dir="auto">Steps to reproduce the behavior</h3>
<h3 dir="auto">Please provide the reproduce example codes (such as github link) if possible.</h3>