問題
JDBC操作MySQL數據庫,當進行插入或更新操作的數據長度超過表字段的聲明最大長度時,會報出以下錯誤,導致不能正常插入:
SQLException: Data truncation: Data too long for column 'diff' at row 2
但是當直接在MySQL客戶端操作時,發現確實可以的,只不過會自動對插入的數據進行截斷處理:
'diff'字段的長度為3,下面插入一個超長的數據'1234':
可以成功插入,並對數據進行了截斷處理,插入結果為'123',不過MySQL發出了警告(warning)。
但是到了JDBC就是SQLException了。
解決
JDBC Driver作為MySQL Client與MySQL Server交互時,JDBC Driver默認會設置會話SQL_MODEL='STRICT_TRANS_TABLES',可以寫一個sql語句:'select @@session.sql_mode;',executeQuery執行以下(詳見最后源碼),默認情況下JDBC的jdbcCompliantTruncation(是否截斷)參數為true,修改為false即可解決。(MySQL本身也可以設置相關的配置,詳見MySQL——SQL Mode詳解)
將JDBC連接的URL改為:
jdbc:mysql://localhost:3306/table_name?jdbcCompliantTruncation=false
不過這樣會存在另外一個問題,嘗試更新int類型的數據,如果插入數據超長(也就是超過可以裝載的大小),將插入字段的最大值:
所以最好的解決辦法還是在程序中做判斷+截斷吧!
也算一種解決方法
問題的產生就是,JDBC並不能對超長的插入字段進行自動截斷處理並順利插入數據,所以如果在SQL中獲得字段的聲明長度,再用MySQL提供的left等截斷函數,也能實現,不過需要子查詢,效率可想而知。
獲得某庫某表某字段的聲明長度SQL:
再加上LEFT()函數:
String update = "update wm_poi_dispatch_setting set diff=LEFT('4567',
(select CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'wm_poi_dispatch_setting' and table_schema = 'poi_test' and column_name = 'diff' limit 0,1)
) " + "where wm_poi_id = 1
";
效率過低,忽略。
源碼

1 package test.jdbc; 2 3 import java.sql.*; 4 5 /** 6 * Created by zhengbin06 on 16/9/14. 7 */ 8 public class DataBaseTest { 9 public static Connection getConnection() throws SQLException, 10 java.lang.ClassNotFoundException { 11 Class.forName("com.mysql.jdbc.Driver"); 12 String url = "jdbc:mysql://localhost:3306/poi_test?jdbcCompliantTruncation=true"; 13 // String url = "jdbc:mysql://localhost:3306/poi_test?jdbcCompliantTruncation=false"; 14 String username = "root"; 15 String password = ""; 16 Connection con = DriverManager.getConnection(url, username, password); 17 return con; 18 } 19 20 public static void main(String args[]) { 21 try { 22 Connection con = getConnection(); 23 Statement sql_statement = con.createStatement(); 24 25 // String query = "select * from wm_poi_dispatch_setting"; 26 String query = "select @@session.sql_mode;"; 27 // String update = "update wm_poi_dispatch_setting set diff=LEFT('4567', (select CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'wm_poi_dispatch_setting' and table_schema = 'poi_test' and column_name = 'diff' limit 0,1)) " + 28 // "where wm_poi_id = 1"; 29 // sql_statement.executeUpdate(update); 30 ResultSet result = sql_statement.executeQuery(query); 31 32 // System.out.println("Student表中的數據如下:"); 33 // System.out.println("------------------------"); 34 // System.out.println("wm_poi_id" + " " + "logistics_id" + " " + "value" + " " + "diff"); 35 // System.out.println("------------------------"); 36 37 // while (result.next()) { 38 // int wm_poi_id = result.getInt("wm_poi_id"); 39 // int logistics_id = result.getInt("logistics_id"); 40 // int value = result.getInt("value"); 41 // String diff = result.getString("diff"); 42 // System.out.println(" " + wm_poi_id + " " + logistics_id + " " + value + " " + diff); 43 // } 44 System.out.println("|@@session.sql_mode|"); 45 while(result.next()) { 46 String sql_mode = result.getString("@@session.sql_mode"); 47 System.out.println(sql_mode); 48 } 49 sql_statement.close(); 50 con.close(); 51 } catch (java.lang.ClassNotFoundException e) { 52 System.err.print("ClassNotFoundException"); 53 System.err.println(e.getMessage()); 54 } catch (SQLException ex) { 55 System.err.println("SQLException: " + ex.getMessage()); 56 } 57 } 58 }