SQL Select * из нескольких таблиц - PullRequest
15 голосов
/ 26 марта 2010

Используя PHP / PDO / MySQL, возможно ли использовать подстановочный знак для столбцов, когда выбор сделан для нескольких таблиц, а возвращенные ключи массива полностью определены, чтобы избежать конфликта имен столбцов?

пример:

SELECT * из таблицы1, таблицы2;

дает:

Ключами массива являются 'table1.id', 'table2.id', 'table1.name' и т. Д.

Я попытался "SELECT table1. *, Table2. * ...", но возвращенные ключи массива не были полностью определены, поэтому столбцы с тем же именем столкнулись и были перезаписаны.

Ответы [ 5 ]

14 голосов
/ 26 марта 2010

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

PDO

Установите атрибут для объекта PDO , а не PDOStatment .

$PDO->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, true);

Вот и все. Затем вы получаете ключи ассоциативного массива, такие как $row['myTable.myColumn']. Это работает, если вы тоже получаете объект (например, через PDO::FETCH_OBJECT), так что будьте осторожны, потому что вам нужно получить доступ к таким свойствам, как $obj->{'myTable.myColumn'}

* В руководстве сказано, что атрибут PDO::ATTR_FETCH_TABLE_NAMES поддерживается только некоторыми драйверами. Если вышеприведенное не работает, вместо этого может работать .

$pdoStatement->setFetchMode(PDO::FETCH_NUM);
$pdoStatement->execute();
//build our associative array keys
$qualifiedColumnNames = array();
for ($i = 0; $i < $pdoStatement->columnCount(); $i++) {
    $columnMeta = $pdoStatement->getColumnMeta($i);
    $qualifiedColumnNames[] = "$columnMeta[table].$columnMeta[name]";
}

//fetch results and combine with keys
while ($row = $pdoStatement->fetch()) {
    $qualifiedRow = array_combine($qualifiedColumnNames, $row);
    print_r($qualifiedRow);
}

Тот же базовый шаблон используется для других расширений базы данных

MySQL

$res = mysql_query($sql);
//build our associative array keys
$qualifiedColumnNames = array();
for ($i = 0; $i < mysql_num_fields($res); $i++) {
    $columnMeta = mysql_fetch_field($res, $i);
    $qualifiedColumnNames[] = "$columnMeta[table].$columnMeta[name]";
}

//fetch results and combine with keys
while ($row = mysql_fetch_row($res)) {
    $qualifiedRow = array_combine($qualifiedColumnNames, $row);
    print_r($qualifiedRow);
}

MySQLi

$res = $mysqli->query($sql);
//build our associative array keys
$qualifiedColumnNames = array();
foreach ($res->fetch_fields() as $columnMeta) {
    $qualifiedColumnNames[] = "{$columnMeta->table}.{$columnMeta->name}";
}

//fetch results and combine with keys
while ($row = $res->fetch_row()) {
    $qualifiedRow = array_combine($qualifiedColumnNames, $row);
    print_r($qualifiedRow);
}

Это также должно работать с псевдонимами таблиц (проверено в php 7.1) - в квалифицированном имени столбца будет использоваться псевдоним таблицы.

4 голосов
/ 26 марта 2010

вы можете сделать это:

SELECT Table1.*,Table2.xyz, Table2.abc,... From...

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

Вы также можете использовать псевдонимы столбцов, где вы «переименовываете» столбец:

SELECT Table1.A AS T1_A,Table2.A AS T2_A,... From...

ваш набор результатов будет иметь столбцы T1_A и T2_A

2 голосов
/ 26 марта 2010

К сожалению, нет; нет синтаксиса SQL для обеспечения уникальности имен столбцов.

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

Я не знаю, какую СУБД вы используете, но что-то вроде этого должно работать на SQL Server:

declare @columns table (idx int identity(1,1), tablename varchar(100), columnname varchar(100))

insert into @columns (tablename, columnname) 
select tablename, columnname

from INFORMATION_SCHEMA.COLUMNS

where tablename in ('table_1', 'table_2')

declare @sql nvarchar(4000)

declare @i int
declare @cnt in

declare @col varchar(100)
declare @table varchar(100)

select @i = 0, @cnt = max(idx), @sql = '' from @columns

while @i < @cnt
begin
    select @i = @i + 1

    select @col = columnname, @table = tablename from @columns where idx = @i

    if len(@sql) > 0
        select @sql = @sql + ', '

    select @sql = @sql + '[' + @table + '].[' + @col + '] as [' + @table + '_' + @col + ']'
end

select @sql = 'select ' + @sql + ' from table_1, table_2'

exec sp_executesql @sql
1 голос
/ 31 мая 2017

Бесстыдно переупаковано из @goat:

// Workaround for setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, true);
function pdoStatementExecuteAndFetchObjWithTableNames(PDOStatement $statement)
{
  $statement->setFetchMode(PDO::FETCH_NUM);
  $statement->execute();

  //build our associative array keys
  $qualifiedColumnNames = array();
  for ($i = 0; $i < $statement->columnCount(); $i++) {
      $columnMeta = $statement->getColumnMeta($i);
      $qualifiedColumnNames[] = "$columnMeta[table].$columnMeta[name]";
  }

  //fetch results and combine with keys
  while ($row = $statement->fetch()) {
      $qualifiedRow = array_combine($qualifiedColumnNames, $row);
      yield (object) $qualifiedRow;
  }  
}

ПРИМЕЧАНИЕ: если вы используете:

ВЫБРАТЬ 1 ИЗ my_table AS my_table_alias

тогда вы получите my_table. Я бы надеялся на my_table_alias. Я получил этот результат с PHP 5.6 и драйвером sqlite.

0 голосов
/ 26 марта 2010

К сожалению, PHP (особенно расширения MySQL, PgSQL, MSSQL) всегда будут перезаписывать ваши столбцы в случае перекрытия.

Я бы порекомендовал создать View в вашей базе данных и присвоить псевдонимы столбцам, чтобы они были "полностью квалифицированными".

Например: (MySQL)

CREATE VIEW viewTable1Table2 AS
    SELECT
        t1.field1 AS Table1Field1
        t2.field1 AS Table2Field1
    FROM Table1 t1
        INNER JOIN Table2 t2
            ON t1.id = t2.id;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...