2015-07-11 40 views
3

我在使用Java將日期輸入到MySQL時遇到了一個固執的問題。在我的代碼中,我將java.util.Date轉換爲java.sql.Date,以便快速輕鬆地匹配日期的SQL格式。MySQL/Java:錯誤日期值:'1990'列

以下是我用來將日期插入數據庫的代碼。 注意:代碼縮短只表示我的問題。

客戶端對象是通過該函數的參數傳遞。

 //Date to Date 
     java.sql.Date sqlBirthday = new java.sql.Date(client.getBirthday().getTime()); 

     System.out.println(sqlBirthday); // Prints YYYY-MM-DD 

     sql = "INSERT INTO clientdata (client_id, weight, height, birthday) VALUES (" + client.getID() + "," + client.getWeight() + "," + client.getHeight().getMeasurementInInches() + "," 
       + sqlBirthday + ")"; 
     statement.execute(sql); 

     statement.close(); 

執行所述代碼,以將數據輸入到數據庫中,我收到以下運行時錯誤後:

com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect date value: '1990' for column 'birthday' at row 1

中的println輸出如下:

1998-05-03

哪個預期產出。

該錯誤的堆棧跟蹤低於,但我懷疑它有多大的用處:

com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect date value: '1990' for column 'birthday' at row 1 
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3833) 
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3771) 
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435) 
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) 
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2531) 
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2489) 
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:848) 
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:742) 
at fitness.traingym.client.utils.DatabaseHandler.createLogin(DatabaseHandler.java:71) 
at fitness.traingym.client.TrainManagement.testClientCreate(TrainManagement.java:47) 
at fitness.traingym.client.TrainManagement.<init>(TrainManagement.java:22) 
at fitness.traingym.client.TrainManagement.main(TrainManagement.java:57) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) 

這很有趣,我遇到了這個錯誤,因爲格式化的日期似乎是正確的SQL句法。

+0

生日是字符串值,用單引號括起來。使用'sql =「INSERT INTO clientdata(client_id,weight,height,birthday)VALUES(」+ client.getID()+「,」+ client.getWeight()+「,」+ client.getHeight()。getMeasurementInInches() +「,'」 + sqlBirthday +「')」;' –

+4

簡短且危險的答案:在日期值周圍放置單引號。長而正確的答案:使用參數化查詢 - 它們更安全(沒有SQL注入的機會,它破壞了職業和財富),而且您不必擔心日期格式或使用單引號轉義的字符串。 –

+0

謝謝Ed的知識,我對SQL相當陌生,並沒有被教過參數化查詢,但在閱讀您的回覆後稍微查找一下後,我發現它非常重要!感謝您的答覆。 – Mamadou

回答

5
解決的是周圍的日期字符串用引號 '問題

最簡單的方式,但使用單引號,這是很下流的手段,必須避免AT全部。要解決這個與參數化查詢工作的最好方法是使用PreparedStatement S:

sql = "INSERT INTO clientdata (client_id, weight, height, birthday) VALUES (?, ?, ?, ?)"; 
PreparedStatement pstmt = connection.prepareStatement(sql); 
pstmt.setInteger(1, client.getID()); 
pstmt.setInteger(2, client.getWeight()); 
pstmt.setInteger(3, client.getHeight()); 
pstmt.setTimestamp(4, new java.sql.Timestamp(client.getBirthday().getTime())); 
pstmt.executeUpdate(); 
pstmt.close(); 
+0

非常感謝你的例子。現在我知道參數化查詢了,我覺得不需要使用它們。 xD – Mamadou

+0

我想我的第二個問題(我覺得答案很明顯)是:我是否正確地認爲PreparedStatements應該用於檢索和提交數據庫? – Mamadou

+0

是的,它們都是值得的。如果您不會將任何參數傳遞給查詢,則直接使用'Statement'當執行DDL語句'CREATE TABLE foo(id INT PRIMARY KEY,val VARCHAR(50))'或類似的語句時。 –

1

問題是日期值需要在傳入數據庫之前嵌入單引號(')中。

更新您的Java字符串以在sqlBirthday的值周圍包含單引號(')。

0

封閉日期值

使用

sql = "INSERT INTO clientdata (client_id, weight, height, birthday) VALUES (" + client.getID() + "," + client.getWeight() + "," + client.getHeight().getMeasurementInInches() + ", '"+ sqlBirthday + "')"; 
                                               ^    ^
0
String date = request.getParameter("date"); 
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); // your template here 
java.util.Date dateStr = formatter.parse(sqlBirthday); 
java.sql.Date dateDB = new java.sql.Date(dateStr.getTime()); 

它傳遞在此java.sql.Date在事先準備好的聲明。