You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java SQL Prepared Statement更新语句执行失败求助排查

问题描述

我遇到了无法运行以下代码的问题,尝试多次修改仍始终报错,烦请帮忙排查问题所在。

TestCommand类代码

public class TestCommand implements ServerCommand{

    @Override
    public void performcommand(SlashCommandInteractionEvent event, Member m, MessageChannelUnion channel,
            VoiceChannel ec, VoiceChannel pub, TextChannel log, Guild guild) {

        Connection connection = null;
        PreparedStatement preparedStatement = null;
                
        String sql = ("UPDATE member_ships SET?= ? WHERE UUID= ?"); 
        
        try {
            connection = MySQL.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"Cyclone");
            preparedStatement.setInt(2,9);
            preparedStatement.setLong(3,316931131188576123l);
            preparedStatement.executeUpdate();
        }   catch (SQLException e) {
            e.printStackTrace();
        } finally {
            MySQL.closePreparedStatement(preparedStatement);
            MySQL.closeConnection(connection);
        }
    }
}

MySQL连接类代码

public class MySQL {

    public static Connection getConnection() throws SQLException {
        Connection connection = DriverManager.getConnection("jdbc:mysql://*****","***","****");
        connection.setAutoCommit(true);
        System.out.println("Database connecion successful"); //TODO Remove 
        return connection;
    }
}

错误栈信息

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''Cyclone'= 9 WHERE UUID= 316931131188576123' at line 1
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
        at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916)
        at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1061)
        at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1009)
        at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1320)
        at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:994)

问题排查与修复

核心问题

PreparedStatement的?占位符只能用来替换SQL中的值,不能替换列名、表名这类数据库对象名称。你的代码中把列名Cyclone通过占位符传入,JDBC会自动给它加上单引号,最终生成的非法SQL为:

UPDATE member_ships SET 'Cyclone'= 9 WHERE UUID= 316931131188576123

列名被单引号包裹后不符合SQL语法,因此抛出语法错误。

修复方案

如果需要动态指定列名,直接在SQL字符串中拼接(必须做合法性校验避免SQL注入),修改后的代码如下:

public class TestCommand implements ServerCommand{

    @Override
    public void performcommand(SlashCommandInteractionEvent event, Member m, MessageChannelUnion channel,
            VoiceChannel ec, VoiceChannel pub, TextChannel log, Guild guild) {

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        
        // 定义要更新的列名
        String columnName = "Cyclone";
        // 校验列名合法性,限制只能使用预设的列名列表
        if (!Arrays.asList("Cyclone", "其他允许的列名").contains(columnName)) {
            // 非法列名,直接终止操作
            return;
        }
        
        // 拼接合法的SQL语句
        String sql = String.format("UPDATE member_ships SET %s= ? WHERE UUID= ?", columnName); 
        
        try {
            connection = MySQL.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,9);
            preparedStatement.setLong(2,316931131188576123L);
            preparedStatement.executeUpdate();
        }   catch (SQLException e) {
            e.printStackTrace();
        } finally {
            MySQL.closePreparedStatement(preparedStatement);
            MySQL.closeConnection(connection);
        }
    }
}

注意事项

  • 动态拼接列名时,必须校验列名是否属于预先定义的合法列表,绝对不能直接拼接用户输入的内容,防止SQL注入攻击。
  • 只有SQL中的值才能使用PreparedStatement的占位符,这是JDBC占位符的核心规则。

内容的提问来源于stack exchange,提问作者Azalen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:10:15