【问题标题】:Replace mysql query table prefix in php在php中替换mysql查询表前缀
【发布时间】:2015-10-21 14:48:37
【问题描述】:

我正在编写一个数据库查询管理器类。在我的类中,表前缀的特征是#__。我想用一个函数将它们替换为表前缀。

我编写的函数运行良好,但速度很慢。我想要一个优化的函数(可能是正则表达式或其他解决方案)。

注意:请记住,#__ 不应被替换为引号。

例子:

SELECT p.*, m.member_name, m.member_alias
FROM #__posts AS p
LEFT JOIN #__members AS m ON m.member_id=p.post_author
WHERE p.post_approve = '1' AND p.post_date <= '1438252218'

INSERT INTO `#__posts` (`post_title`, `post_text`) 
VALUES ('post title (maybe include #__ )'  , 'post text. it also can include #__')

我的功能:

protected function replace_prefix($sql, $prefix = '#__') 
{
    $done = null;
    $single = false;
    $double = false;
    $found = false;
    $i = 0;
    while (strlen($sql) > 0)
    {
        if ($sql[$i] == null)
        {
            return $done.$sql;
        }
        if (($sql[$i] == "'") && $sql[$i-1] !='\\')
        {
            $single = !$single;
        }
        if (($sql[$i] == '"') && $sql[$i-1] !='\\')
        {
            $double = !$double;
        }

        if ($sql[$i] == $prefix[0] && !$single && !$double)
        {
            $found = true;
            for ($j=0; $j < strlen($prefix); $j++)
            {
                if ($sql[$i+$j] != $prefix[$j])
                {
                    $found = false;
                    break;
                }
            }
        }
        if ($found)
        {
            $done .= substr($sql, 0, $i).$this->prefix;
            $sql = substr($sql, $i+$j);
            $found = false;
            $i = 0;
        }
        else
        {
            $i++;
        }

        if ($i >= strlen($sql))
        {
            return $done.$sql;
        }
    }
    return $done;
}

【问题讨论】:

  • 一个技巧是,而不是逐个字符..只需将所有 "#_ 和 '#_ 替换为临时字符串.. 然后将所有 #_ 替换为您的值,最后替换回 temp '#_ 或 "#_ 的字符串
  • 如果它在一个字符串中,例如:“这个 #__ 是前缀”。
  • 你能列出所有可能的 $SQL 字符串吗?也许是时候使用正则表达式和切片函数了
  • 这是开源类,所以任何人都可以做任何事情
  • 您仍然可以将上述技巧与正则表达式和小功能一起使用。我不是 PHP 专家,但这个解决方案应该可以帮助您:stackoverflow.com/a/10524283/1684486 只需使用上述函数将引号内的所有 #_ 替换为临时字符串,然后将所有 #_ 替换为您的值,然后替换回临时字符串

标签: php mysql sql regex


【解决方案1】:

你知道表的名称吗?例如,如果您有一个表#__Contacts,您可以执行以下操作:

$sql2 = str_replace( $prefix . $table, $new_prefix . $table, $sql );

如果您使用replace_prefix() 方法进行琐碎查询(不是复杂查询),它应该可以解决问题。

【讨论】:

  • 不,我没有。此类用于模块化 CMS。这样任何人都可以添加或删除表格。
  • 您能否向我们发送一些将通过您的replace_prefix() 方法传递的查询?
  • 那么,您测量脚本的执行时间了吗?你能给我们一个估计的第一个样本查询的时间吗?我虽然关于使用SHOW TABLES 的解决方案,但我不确定它是否会产生更好的性能影响或会使事情变得更糟。
  • 不显示表格是一个糟糕的解决方案。如果我们找到引号并用某些东西重新替换它们然后使用 str_replace ???
【解决方案2】:

我终于找到了一个好方法!此功能比旧功能快 30 倍:

protected function replace_prefix($sql, $prefix = '#__') 
{
    $array = array();
    if($number = preg_match_all( '#((?<![\\\])[\'"])((?:.(?!(?<![\\\])\1))*.?)\1#i', $sql, $matches))
    {
        for ($i = 0; $i < $number; $i++)
        {
            if (!empty($matches[0][$i]))
            {
                $array[$i] = trim($matches[0][$i]);
                $sql = str_replace($matches[0][$i], '<#encode:'.$i.':code#>', $sql);
            }
        }
    }

    $sql = str_replace($prefix, $this->prefix , $sql);

    foreach ($array as $key => $js)
    {
        $sql = str_replace('<#encode:'.$key.':code#>', $js, $sql);
    }

    return $sql;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    相关资源
    最近更新 更多