如何从mysql查询中识别字段的源表

时间:2009-05-07 12:44:47

标签: php mysql

我有两个动态表(tabx和taby),它们是通过php界面创建和维护的,其中可以添加,删除,重命名列等。 我想从两个表中同时阅读所有列,如下所示; -

从tabx中选择*,taby在哪里......;

我希望能够从查询结果中判断每列是来自tabx还是taby - 是否有办法强制mysql返回完全限定的列名,例如tabx.col1,tabx.col2,taby.coln等?

5 个答案:

答案 0 :(得分:1)

在PHP中,您可以从结果中获取字段信息,就像这样(从我很久以前写过的项目中窃取):

/*
Similar to mysql_fetch_assoc(), this function returns an associative array
given a mysql resource, but prepends the table name (or table alias, if
used in the query) to the column name, effectively namespacing the column
names and allowing SELECTS for column names that would otherwise have collided
when building a row's associative array.
*/
function mysql_fetch_assoc_with_table_names($resource) {
    // get a numerically indexed row, which includes all fields, even if their names collide
    $row = mysql_fetch_row($resource);
    if( ! $row)
        return $row;

    $result = array();

    $size = count($row);    
    for($i = 0; $i < $size; $i++) {
        // now fetch the field information
        $info = mysql_fetch_field($resource, $i);
        $table = $info->table;
        $name = $info->name;
        // and make an associative array, where the key is $table.$name
        $result["$table.$name"] = $row[$i];  // e.g. $result["user.name"] = "Joe Schmoe";
    }

    return $result;
}

然后你可以像这样使用它:

$resource = mysql_query("SELECT * FROM user JOIN question USING (user_id)");
while($row = mysql_fetch_assoc_with_table_names($resource)) {
    echo $row['question.title'] . ' Asked by ' . $row['user.name'] . "\n";
}

所以直接回答你的问题,表名数据总是由MySQL发送 - 由客户端告诉你每列的来源。如果你真的希望MySQL明确地返回每个列名,你需要修改你的查询以明确地进行别名,比如@Shabbyrobe建议。

答案 1 :(得分:0)

select * from tabx tx, taby ty where ... ;

答案 2 :(得分:0)

的作用:

SELECT tabx.*, taby.* FROM tabx, taby WHERE ...

工作?

答案 3 :(得分:0)

撇开任何关于你为什么要这样做的问题,以及为什么你想要在这里进行交叉连接,这是我能想到的最佳方式。

您可以尝试在每个表上执行EXPLAIN,并从结果中以编程方式构建select语句。这是一个糟糕的脚本示例,它将为您提供带有别名的动态生成的字段列表。这将增加您执行的查询数量,但动态生成的查询中的每个表都会导致触发EXPLAIN查询(尽管可以通过缓存相当容易地减轻这种情况)。

<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
function aliasFields($pdo, $table, $delim='__') {
    $fields = array();
    // gotta sanitise the table name - can't do it with prepared statement
    $table = preg_replace('/[^A-z0-9_]/', "", $table);
    foreach ($pdo->query("EXPLAIN `".$table."`") as $row) {
        $fields[] = $table.'.'.$row['Field'].' as '.$table.$delim.$row['Field'];
    }
    return $fields;
}
$fieldAliases = array_merge(aliasFields($pdo, 'artist'), aliasFields($pdo, 'event'));
$query = 'SELECT '.implode(', ', $fieldAliases).' FROM artist, event';
echo $query;

结果是一个看起来像这样的查询,表和列名称由两个下划线分隔(或者您喜欢的任何分隔符,请参阅aliasFields()的第三个参数):

// ABOVE PROGRAM'S OUTPUT (assuming database exists)
SELECT artist__artist_id, artist__event_id, artist__artist_name, event__event_id, event__event_name FROM artist, event

从那里,当您迭代结果时,您可以使用相同的分隔符对每个字段名称进行爆炸以获取表名称和字段名称。


John Douthat的回答比上述要好得多。仅在数据库未返回字段元数据时才有用,因为某些驱动程序可能存在PDO威胁。

这是一个简单的代码片段,介绍如何使用PDO而不是mysql _ *()来完成John的建议:

<?php

$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

$query = 'SELECT artist.*, eventartist.* FROM artist, eventartist LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute();

while ($row = $stmt->fetch()) {
    foreach ($row as $key=>$value) {
        if (is_int($key)) {
            $meta = $stmt->getColumnMeta($key);
            echo $meta['table'].".".$meta['name']."<br />";
        }
    }
}

答案 4 :(得分:0)

我想知道你想要完成什么。首先,在表格中添加和删除列是一种奇怪的做法;这意味着您的数据架构在运行时正在发生变化。

此外,要同时从两个表中查询,它们之间应该存在某种关系。一个表中的行应该以某种方式与另一个表的行相关联。如果不是这种情况,最好再做两个单独的SELECT查询。

您的问题的答案已经给出:SELECT tablename。*来检索给定表中的所有列。如果两个表中都有相同名称的列,这可能会也可能无法正常工作;你应该在文档中查看。

您能否提供有关您要解决的问题的更多信息?我认为你很有可能以错误的方式解决这个问题。