2011-06-14 64 views
3

這使我瘋狂......我在這裏做錯了什麼?Java PreparedStatement抱怨execute()上的SQL語法

ArrayList<String> toAdd = new ArrayList<String>(); 
toAdd.add("password"); 
try{ 
    PreparedStatement pStmt = conn.prepareStatement("ALTER TABLE testTable ADD ? varchar(100)"); 
     for (String s : toAdd) { 
      pStmt.setString(1, s); 
      pStmt.execute(); 
     } 
} catch (SQLException e) { 
    e.printStackTrace(); 
} 

結果...

02:59:12885錯誤[STDERR] com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:您的SQL語法錯誤;檢查對應於你的MySQL服務器版本正確的語法使用近「」密碼「VARCHAR(100)」在1號線

的手冊,但...

ArrayList<String> toAdd = new ArrayList<String>(); 
toAdd.add("password"); 
try{ 
    Statement stmt = conn.prepareStatement(); 
     for (String s : toAdd) { 
      stmt.execute("ALTER TABLE testTable ADD "+s+" varchar(100)"); 
     } 
} catch (SQLException e) { 
    e.printStackTrace(); 
} 

作品完美地..所以直接將文本直接輸入MySQL命令行客戶端。

mysql> alter table testTable add stringGoesHere varchar(100); 
Query OK, 1 row affected (0.23 sec) 
Records: 1 Duplicates: 0 Warnings: 0 

我在做什麼錯?

回答

9

MySQL manual明確表示?(參數標記)僅用於綁定數據值,不適用於列名。

參數標記只能使用 其中數據值應該出現,不 SQL關鍵字,標識符等 等等。

所以你將不得不使用你的第二種方法。

+0

啊,謝謝。我會給你一個upvote,但它不會讓我呢。;) – Mike 2011-06-14 07:41:58

+0

在Oracle,SQL Server,DB2,Teradata和我所使用過的每個其他關係數據庫中都可以找到相同的限制。限制與優化程序處理SQL語句的方式有關。在執行查詢計劃時,綁定值在處理中提供*太晚*。對於語法檢查,關鍵字需要提前提供。在開發/選擇查詢計劃之前,必須在語義檢查期間識別表,列,函數等。執行查詢計劃之前不會提供綁定值。 – spencer7593 2016-03-24 14:35:02

-1

您不能使用像這樣的參數提交ALTER TABLE語句。

我想在Java PreparedStatement中執行DDL語句是不允許的。

-1

請嘗試使用以下內容

pStmt.executeUpdate();

pStmt.close();

1

JDBC中的佔位符用於數據,而不是表,列,視圖或函數名稱。理由很充分。應用程序的數據庫模式大部分時間都是靜態的,只是很少發生變化。讓他們充滿活力沒有任何好處。

+0

是的,綁定參數/佔位符只能用於*值*。不用於標識符或關鍵字。限制主要是由於SQL優化器(SQL數據庫中的SQL語句如何處理)。該限制不是特定於JDBC的。 (在這個答案中給出的原因似乎是似是而非的。) – spencer7593 2016-03-24 13:59:41

1

準備好的語句需要定義一個固定的結構,以便它們可以被預編譯。這意味着您可以使用變量的值,但從來沒有可變的表名稱,列名稱,函數名稱等。

1

使用預處理語句時,您的參數類似於字符串文字處理。因此,您的語句等同於「ALTER TABLE testTable ADD \'」+ s +「\'varchar(100)」。請注意錯誤消息中字段名稱周圍的單引號。

我會建議在這種情況下建立一個文字陳述,而不是試圖使用準備好的陳述。