#php #oracle #pdo #case-sensitive
#php #Oracle #pdo #чувствителен к регистру
Вопрос:
Я хочу использовать библиотеку php, которая использует PDO. И я хочу использовать с ним базу данных Oracle.
Проблема в том, что авторы этой библиотеки используют идентификаторы без кавычек в своих запросах, например:
$statement = $pdo->prepare('SELECT * from some_table where some_column = :some_column');
$statement->execute(['some_column' => 'some value']);
$result = $statement->fetch(PDO:FETCH_ASSOC);
return $result['some_other_column'];
В этом случае Oracle преобразует регистр идентификаторов в ВЕРХНИЙ, но авторы предполагают, что регистр ниже, поэтому возникает undefined index
ошибка php.
Как мне обойти это?
UPD. Я пытался использовать нижний регистр при создании объектов базы данных, например:
CREATE TABLE "some_table"
(
"some_column" VARCHAR(10),
"some_other_column" VARCHAR(10)
);
— но в этом случае Oracle выдает ошибку при выполнении SELECT
приведенного выше оператора, потому что идентификаторы в нем преобразуются в ВЕРХНИЙ регистр, в то время как имена объектов указаны в нижнем регистре.
UPD 2.
Я не должен редактировать исходный код сторонней библиотеки — нужно как-то настроить мою среду и соединение: Oracle, PHP, PDO.
Комментарии:
1. Я не знаю PHP, но — что касается Oracle — если вы хотите сохранить регистр букв, заключите эти идентификаторы в двойные кавычки. Посмотрите, поможет ли это.
3. @Littlefoot как мне это сделать, если я не разработчик этой библиотеки? Вы предлагаете перезаписать их код в каждом месте, где они используют SQL-запрос?
4. Э-э, нет. Как я уже сказал, я не знаю PHP, я понятия не имею, как это на самом деле работает. Я надеюсь, что кто-то еще сможет помочь.
5. @Yourcommon Sense, IMO, pdo уже использует case_natural — вот почему он возвращает результат в верхнем регистре. но вы дали мне хорошую идею — я попытаюсь заставить его использовать нижний регистр (потому что авторы библиотеки используют нижний регистр) — может быть, это поможет
Ответ №1:
Я нашел решение для своего случая, благодаря Your Common Sense
комментарию.
При инициализации библиотеки я передаю ей объект PDO — я настроил его так, чтобы он всегда использовал нижний регистр, с помощью следующего кода:
$options = [
PDO::ATTR_CASE => PDO::CASE_LOWER,
];
$connection = new PDO($dsn, $username, $password, $options);
init3rdPartyLibrary($connection);
Из-за этого ключи $result
переменной, возвращаемой by $statement->fetch()
, теперь строчные, и поэтому библиотека работает так, как ожидали ее авторы.
Ответ №2:
Если вы хотите использовать идентификаторы в нижнем регистре, то, как вы написали в вопросе, вам нужно заключить их в двойные кавычки в Oracle:
CREATE TABLE "some_table"
(
"some_column" VARCHAR(10),
"some_other_column" VARCHAR(10)
);
Если вы использовали идентификаторы, чувствительные к регистру, вам ВСЕГДА нужно будет заключать их в кавычки каждый раз, когда они используются. Итак, ваш оператор SQL в PHP должен быть:
$statement = $pdo->prepare('SELECT * from "some_table" where "some_column" = :some_column');
После того, как вы заключили их в кавычки, идентификаторы будут соответствовать значениям в базе данных, и возвращаемый результирующий набор также должен содержать идентификаторы столбцов в нижнем регистре.
Как мне обойти это?
Из документации Oracle Database Object Names and Qualifiers:
Правила именования объектов базы данных
У каждого объекта базы данных есть имя. В инструкции SQL вы представляете имя объекта с идентификатором в кавычках или идентификатором без кавычек.
- Идентификатор, заключенный в кавычки, начинается и заканчивается двойными кавычками («). Если вы называете объект схемы, используя идентификатор, заключенный в кавычки, вы должны использовать двойные кавычки всякий раз, когда ссылаетесь на этот объект.
- Идентификатор без кавычек не окружен никакими знаками препинания.
Вы можете использовать идентификаторы в кавычках или без кавычек для именования любого объекта базы данных.
…
- Идентификаторы без кавычек не чувствительны к регистру. Oracle интерпретирует их как прописные. Идентификаторы, заключенные в кавычки, чувствительны к регистру.
Это означает, что вы не можете обойти это в Oracle, поскольку именно так должен вести себя Oracle. Вы либо заключаете идентификаторы в кавычки (везде, где они используются) и можете использовать идентификаторы в нижнем регистре, либо Oracle неявно преобразует идентификаторы без кавычек в верхний регистр.