【问题标题】:Is there a way to search all the tables in a mySQL database?有没有办法搜索 mySQL 数据库中的所有表?
【发布时间】:2011-05-19 23:54:25
【问题描述】:

基本上我有一个充满表格的数据库,我想遍历所有表格,直到找到与我的搜索查询匹配的结果。有没有办法做到这一点?或者至少是一个返回所有表名的命令,以便我可以遍历它们直到找到正确的值?

谢谢!

【问题讨论】:

  • 我怀疑这可以通过动态 SQL 轻松完成。查询一些包含所有表名和列名的元表,然后遍历该结果集并根据需要查询表和列。不作为答案发布,因为我不确定这在 MySQL 中是否可行(尽管我知道类似的技巧在 Oracle 中有效)

标签: php search mysql search-engine


【解决方案1】:

啊,搜索引擎。令人兴奋的主题,但我宁愿用内部智能构建一些东西,而不是使用蛮力解决方案。是的 - 检查数据库中的每个表/列是蛮力的,可能会导致反应迟缓和误报。

让我向您介绍一些我会使用的东西。使用以下解决方案需要手动添加每个值得扫描的表/列,但其他一切都是自动的。用法如下:

$e = new SearchEngine();
$e->addTable('users', 'id', 'login'); // table, primary key name, column to be searched in
$e->addTable('users', 'id', 'last_name');
$e->addTable('towns', 'id', 'name');

print_r($e->search('austin')); // we search for exact match for word "austin"

以下是它的实现方式:

class SearchEngine {

    protected $tables = array();

    public function addTable($table, $key, $column) {
        $this->tables[] = array(
            'table' => $table,
            'key' => $key,
            'column' => $column
        );
    }

    public function search($term) {
        $q = array();
        foreach ($this->tables as $t) {
            list($table, $key, $column) = $t;
            $q[] = "
                SELECT
                    $key AS searched_key,
                    '$key' AS searched_key_name,
                    '$table' AS searched_table,
                    '$column' AS searched_column,
                    $column AS searched_value
                FROM $table
                WHERE $column = $term
            ";
        }
        $sql = implode(' UNION ', $q);
        // query the database
        // return results
    }

} // class SearchEngine

让我们分析示例输出:

searched_key | searched_key_name | searched_table | searched_column | searched_value
-------------+-------------------+----------------+-----------------+---------------
         276 |                id | users          | login           | austin
        1782 |                id | users          | last_name       | austin
          71 |                id | towns          | name            | austin

从上表中,您可以找出短语“austin”在表users、列login(主键276)和列last_name(主键1782)中找到。在name列(主键71)的表towns中也发现了它;

这样的搜索结果可能对您来说已经足够了。否则,您可以进一步处理列表以从每个表中选择整行:

$out = array();
foreach ($rows as $row) {
    $sql = "
        SELECT * FROM {$row['searched_table']}
        WHERE {$row['searched_key_name']} = {$row['searched_key']}
        LIMIT 1
    ";
    // query the database
    // append result to $out array
}
return $out;

这样您将获得完整的搜索结果(与上表的中间结果相反):

id: 276, login: austin, last_name: Powers, email: austin.powers@gmail.com
id: 1782, login: michael, last_name: austin, email: michael.e@gmail.com
id: 71, name: austin, state: texas, country: usa

由于当前的实现仅限于固定比较运算符(WHERE 字段 = 值),因此您可能希望在此处引入一些灵活性。如果是这样,则需要将搜索运算符委托给外部类并注入search()函数:

public function search(SearchOperator $operator, $term) {
...

然后SearchOperator 需要考虑通过将 WHERE 条件替换为以下内容:

WHERE {$operator->toSQL($column, $term)}

现在让我们关注SearchOperator 的实现。由于操作符实现只提供了一种方法,即toSQL,我们不需要完整的类,甚至不需要抽象类。在这种情况下,接口就足够了:

interface SearchOperator {

    public function toSQL($column, $term);

} // interface SearchOperator

让我们定义几个代表=(等于)和LIKE运算符的实现:

class Equals implements SearchOperator {

    public function toSQL($column, $term) {
        return "$column = '$term'";
    }

} // class Equals

class Like implements SearchOperator {

    public function toSQL($column, $term) {
        return "$column LIKE '$term'";
    }

} // class Like

当然,任何其他实现都是可能的 - 考虑名为 StartsWith、EndsWith 或 DoesNotContain 的类。

查看更新的解决方案使用情况:

$e = new SearchEngine();
$e->addTable('users', 'id', 'login');
$e->addTable('users', 'id', 'last_name');
$e->addTable('towns', 'id', 'name');

print_r($e->search(new Like(), 'austin%')); // here we search for columns being LIKE 'austin%'

是时候留下一些最后的评论了:

  • 以上示例不完整。为清楚起见,省略了数据库查询代码。
  • 示例中使用的 SQL 不会清理输入数据。我强烈建议您使用带有绑定参数的预处理语句以避免巨大的安全风险。
  • 上面介绍的搜索算法是一种幼稚的算法。可以进行一些优化(即对引用同一个表的查询进行分组)。但不要过早优化 - 等到它成为一个真正的问题。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    非常糟糕的主意。但是,如果您需要搜索 all tables(并且您使用的是 MySQL),您可以得到一个列表:

    SHOW TABLES;
    

    然后遍历每个并(假设您知道列)查询它们。

    【讨论】:

    • 请问为什么这是个坏主意?它只是资源密集型的吗?整个数据库只有不到 2000 行,所以比较小。
    【解决方案3】:

    我猜你可以使用 Mysql 的 full-text search 来做这个?

    【讨论】:

      【解决方案4】:

      正如其他人所说,可以从元数据字典中提取所有表名及其列名。看一下“information_schema”数据库。您可以获得一个表列表,然后可以对其进行迭代。

      但是您很可能使用错误的数据库。我们不查询数据库,我们查询数据模型。数据模型被实现为一组表/视图等。

      您能否向我们提供一些背景信息,说明您为什么需要这样做?也许有更好的选择?

      【讨论】:

        【解决方案5】:

        您可以使用

        获取数据库中的所有表
        SHOW TABLES;
        

        然后你可以遍历表并找出每个表的结构

        DISPLAY table_name;
        

        但是您仍然需要对如何查询每个表的列以找到任何内容有一个模糊的概念。因此,除非您有更专业的问题,例如所有表都具有相同的已知结构,我同意您可能使用错误的数据库并且可能有更好的方法的观点。

        【讨论】:

          【解决方案6】:

          有一个不错的库可以读取所有表格,ridona

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-09-05
            • 1970-01-01
            • 2011-02-15
            • 1970-01-01
            • 1970-01-01
            • 2018-09-08
            相关资源
            最近更新 更多