问题描述
我想使用使用PDO的PHP库。我想将它与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将标识符的大小写转换为UPPER,但是作者认为大小写较小,因此发生undefined index
PHP错误。
我该如何绕过?
UPD。我在创建数据库对象时尝试使用小写字母,例如:
CREATE TABLE "some_table"
(
"some_column" VARCHAR(10),"some_other_column" VARCHAR(10)
);
-,但是在这种情况下,Oracle在执行上面的SELECT
语句时会引发错误,因为其中的标识符转换为大写,而对象名称为小写。
UPD 2。
我不应该编辑第三方库的源代码-必须以某种方式配置我的环境和连接:Oracle,PHP,PDO。
解决方法
由于Your Common Sense
的评论,我找到了解决方案。
初始化库时,我向它传递了一个PDO对象-通过以下代码,我将其配置为始终使用小写字母:
$options = [
PDO::ATTR_CASE => PDO::CASE_LOWER,];
$connection = new PDO($dsn,$username,$password,$options);
init3rdPartyLibrary($connection);
因此,$result
返回的$statement->fetch()
变量的键现在是小写字母,因此该库按其作者的预期工作。
如果您要使用小写字母标识符,那么就像您在问题中所写的那样,您需要在Oracle中双引号:
CREATE TABLE "some_table"
(
"some_column" VARCHAR(10),"some_other_column" VARCHAR(10)
);
如果您使用了区分大小写的标识符,则每次使用它们时,始终都需要引用它们。因此,您在PHP中的SQL语句应为:
$statement = $pdo->prepare('SELECT * from "some_table" where "some_column" = :some_column');
一旦在其中引用了它们,则标识符将与数据库中的值匹配,并且返回的结果集也应具有小写的列标识符。
我该如何绕过?
摘自Oracle Database Object Names and Qualifiers文档:
数据库对象命名规则
每个数据库对象都有一个名称。在SQL语句中,您用带引号的标识符或未带引号的标识符表示对象的名称。
- 带引号的标识符以双引号(“)开头和结尾。如果使用带引号的标识符命名架构对象,则在引用该对象时必须使用双引号。
- 未加引号的标识符不包含任何标点符号。
您可以使用带引号或不带引号的标识符来命名任何数据库对象。
...
- 未加引号的标识符不区分大小写。 Oracle将它们解释为大写。带引号的标识符区分大小写。
这意味着您不能在Oracle中绕过此操作,因为这是Oracle旨在表现的方式。您可以使用引号(在所有使用位置的标识符)并且可以使用小写的标识符,或者Oracle将隐式将未使用引号的标识符转换为大写。