как определить исходную таблицу полей из запроса MySQL - PullRequest
0 голосов
/ 07 мая 2009

У меня есть две динамические таблицы (tabx и taby), которые создаются и поддерживаются через интерфейс php, где столбцы можно добавлять, удалять, переименовывать и т. Д. Я хочу прочитать все столбцы одновременно из двух таблиц, как это; -

выберите * из таблицы, таб, где ...;

Я хочу, чтобы по результатам запроса я мог определить, был ли каждый столбец получен из tabx или taby - есть ли способ заставить mysql возвращать полностью определенные имена столбцов, например, tabx.col1, tabx.col2, taby.coln и т. д.?

Ответы [ 5 ]

1 голос
/ 07 мая 2009

В 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.

0 голосов
/ 07 мая 2009

Мне интересно, что вы пытаетесь достичь. Прежде всего, добавление и удаление столбцов из таблицы - странная практика; это означает, что схема ваших данных изменяется во время выполнения.

Кроме того, чтобы запрашивать две таблицы одновременно, между ними должна быть какая-то связь. Строки в одной таблице должны быть каким-то образом соотнесены со строками другой таблицы. Если это не так, лучше выполнить два отдельных запроса SELECT.

Ответ на ваш вопрос уже дан: ВЫБЕРИТЕ имя таблицы. * Чтобы получить все столбцы из данной таблицы. Это может или не может работать правильно, если в обеих таблицах есть столбцы с одинаковыми именами; Вы должны найти это в документации.

Не могли бы вы дать нам больше информации о проблеме, которую вы пытаетесь решить? Я думаю, что есть хороший шанс, что вы поступите неправильно.

0 голосов
/ 07 мая 2009

ли:

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

работа

0 голосов
/ 07 мая 2009

Оставляя в стороне любые вопросы о том, почему вы, возможно, захотите это сделать, и почему вы вообще хотели бы сделать здесь кросс-соединение, вот лучший способ, которым я могу придумать это из головы.

Вы можете попробовать выполнить EXPLAIN для каждой таблицы и построить оператор выбора программно из результата. Вот плохой пример скрипта, который даст вам динамически генерируемый список полей с псевдонимами. Это увеличит количество выполняемых вами запросов, поскольку каждая таблица в динамически сгенерированном запросе будет вызывать выполнение запроса 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

Оттуда, когда вы перебираете результаты, вы можете просто выполнить разнесение для каждого имени поля с одинаковым разделителем, чтобы получить имя таблицы и имя поля.


Ответ Джона Даута намного лучше, чем выше. Это было бы полезно, только если метаданные поля не были возвращены базой данных, поскольку угрозы для PDO могут иметь место в некоторых драйверах.

Вот простой фрагмент того, как сделать то, что Джон предположил, используя PDO вместо mysql _ * ():

<?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 />";
        }
    }
}
0 голосов
/ 07 мая 2009
select * from tabx tx, taby ty where ... ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...