Java PreparedStatement жалуется на синтаксис 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:12,885 ОШИБКА [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

Что я делаю не так?


person Mike    schedule 14.06.2011    source источник


Ответы (6)


В руководстве по MySQL ясно сказано, что ? (маркеры параметров) предназначены для только значения данных привязки, а не имена столбцов.

Маркеры параметров можно использовать только там, где должны появляться значения данных, а не для ключевых слов SQL, идентификаторов и т. д.

Поэтому вам придется использовать второй подход.

person dogbane    schedule 14.06.2011
comment
Ах, спасибо. Я бы проголосовал за вас, но мне пока не позволяют. ;) - person Mike; 14.06.2011
comment
Это же ограничение есть в Oracle, SQL Server, DB2, Teradata и любой другой реляционной базе данных, с которой я работал. Ограничение связано с тем, как оператор SQL обрабатывается оптимизатором. Значения связывания предоставляются слишком поздно в процессе обработки, когда выполняется план запроса. Ключевые слова должны быть доступны ранее для проверки синтаксиса. А таблицы, столбцы, функции и т. д. должны быть идентифицированы во время проверки семантики до разработки/выбора плана запроса. Значения привязки не предоставляются до тех пор, пока не будет выполнен план запроса. - person spencer7593; 24.03.2016

Заполнители в JDBC предназначены для данных, а не для имен таблиц, столбцов, представлений или функций. И не зря. Схема БД приложения большую часть времени статична и меняется редко. Нет никаких преимуществ, делающих их динамичными.

person musiKk    schedule 14.06.2011
comment
Да, параметры/заполнители привязки можно использовать только для значений. Не для идентификаторов или ключевых слов. Ограничение в первую очередь связано с оптимизатором SQL (как оператор SQL обрабатывается в базе данных). Это ограничение не относится к JDBC. (Причина, указанная в этом ответе, является благовидной.) - person spencer7593; 24.03.2016

Подготовленные операторы должны определять фиксированную структуру, чтобы их можно было предварительно скомпилировать. Это означает, что у вас могут быть переменные значения, но никогда не могут быть имена переменных таблиц, имен столбцов, имен функций и т. д.

person Landei    schedule 14.06.2011

При использовании подготовленного оператора ваш параметр обрабатывается аналогично строковому литералу. В результате ваше утверждение эквивалентно "ALTER TABLE testTable ADD \'"+s+"\' varchar(100)". Обратите внимание на одинарные кавычки вокруг имени поля в сообщении об ошибке.

Я бы предложил построить буквальное выражение в этом случае, а не пытаться использовать подготовленное выражение.

person Justin Guertin    schedule 14.06.2011

Вы не можете отправить оператор ALTER TABLE с такими параметрами.

Я предполагаю, что недопустимо выполнять операторы DDL в Java PreparedStatement.

person Talha Ahmed Khan    schedule 14.06.2011

Попробуйте использовать следующее

pStmt.executeUpdate();

pStmt.close();

person gmhk    schedule 14.06.2011