SQL从多个表中选择*

时间:2010-03-26 13:41:16

标签: php sql mysql database pdo

使用PHP / PDO / MySQL是否可以在多个表上执行select时对列使用通配符,并且返回的数组键完全限定以避免列名冲突?

示例:

SELECT * from table1,table2;

给出:

数组键是'table1.id','table2.id','table1.name'等。

我尝试了“SELECT table1。*,table2。* ...”但返回的数组键不是完全限定的,因此具有相同名称的列会发生冲突并被覆盖。

5 个答案:

答案 0 :(得分:14)

是的,你可以。最简单的方法是使用pdo,尽管至少有一些其他扩展能够实现它。

pdo

PDO对象上设置属性,而不是PDOStatment

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

就是这样。然后你得到像$row['myTable.myColumn']这样的关联数组键。如果你也获取一个对象(例如通过PDO::FETCH_OBJECT),它也很有效,因为你需要访问像$obj->{'myTable.myColumn'}这样的属性

*只有某些驱动程序支持manual says 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中测试) - 限定列名将使用表别名。

答案 1 :(得分:4)

你可以这样做:

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

您可以使用“*”从一个表中获取所有列,然后使用您需要的另一个表中的列,这样就不会发生冲突。

您还可以使用列别名,“重命名”列:

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

您的结果集将是列T1_A和T2_A

答案 2 :(得分:2)

不幸的是,没有;没有用于确保列名唯一的SQL语法。

如果你真的不知道列的名称并且必须使用SELECT *,那么你唯一真正的选择就是恢复一些非常难看的动态SQL,它可以检查表的结构并生成一个查询将使用表名前缀显式选择它们。

我不知道你使用的是哪个RDBMS,但是这样的东西应该适用于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

答案 3 :(得分:1)

从@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;
  }  
}

注意:如果您使用:

  

SELECT 1 FROM my_table AS my_table_alias

然后你会得到my_table。我希望my_table_alias。我用PHP 5.6和sqlite驱动程序得到了这个结果。

答案 4 :(得分:0)

不幸的是,PHP(特别是MySQL,PgSQL,MSSQL扩展)在重叠的情况下总是会覆盖您的列。

我建议您在数据库中创建一个View,并为您的列添加Alias以使其“完全合格”。

例如:(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;

语法可能不完美,但你可以大致了解我在说什么。