用于预准备语句的Preg_replace解决方案

时间:2009-09-08 20:54:48

标签: sql preg-replace

我有一个命令类,它抽象几乎所有特定的数据库函数(我们在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

1 个答案:

答案 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()谓词中的值列表。但是你正在创造一个非常漏洞的抽象。