我有一个命令类,它抽象几乎所有特定的数据库函数(我们在Mssql 2005(使用ODBC和本机mssql库),MySQL和Oracle上运行完全相同的应用程序。但有时我们的prepare方法有一些问题在执行时,将所有占位符替换为各自的值。但问题是我使用以下内容:
if(is_array($Parameter['Value']))
{
$Statement = str_ireplace(':'.$Name, implode(', ', $this->Adapter->QuoteValue($Parameter['Value'])), $Statement);
}
else
{
$Statement = str_ireplace(':'.$Name, $this->Adapter->QuoteValue($Parameter['Value']), $Statement);
}
当我们有两个或类似的参数名称时出现问题,例如session_browser和session_browse_version ......第一个将部分替换最后一个。
当然我们学会了在特定顺序中指定参数,但现在我有一些“自由”时间我想让它变得更好,所以我在考虑切换到preg_replace ...而且我不是很好在正则表达式中,任何人都可以使用正则表达式来帮助替换像':parameter_name`这样的字符串吗?
最诚挚的问候, Bruno B B Magalhaes
答案 0 :(得分:2)
您应该使用\b
metacharacter来匹配单词边界,这样您就不会在较长的参数名称中意外匹配短参数名称。
此外,如果您将标量值强制转换为一个条目的数组,则不需要特殊情况数组:
preg_replace("/:$Name\b/",
implode(",", $this->Adapter->QuoteValue( (array) $Parameter['Value'] )),
$Statement);
但请注意,当标识符或字符串文字包含看起来像参数占位符的模式时,这可能会产生误报:
SELECT * FROM ":Name";
SELECT * FROM Table WHERE column = ':Name';
当引用的标识符和字符串文字可以包含转义引号时,这会变得更加复杂。
SELECT * FROM Table WHERE column = 'word\':Name';
您可能希望在准备期间重新考虑将变量插入到SQL字符串中,因为您在安全性或性能方面打败了预准备语句的任何好处。
我理解你为什么要做你正在做的事情,因为并非所有RDBMS后端都支持命名参数,并且SQL参数也不能用于IN()
谓词中的值列表。但是你正在创造一个非常漏洞的抽象。