我想知道这在SQL中是否可行。假设你有两个表A和B,你在表A上做一个选择,在表B上做一个连接:

SELECT a.*, b.* FROM TABLE_A a JOIN TABLE_B b USING (some_id);

如果表A有“a_id”、“name”、“some_id”列,表B有“b_id”、“name”、“some_id”列,查询将返回“a_id”、“name”、“some_id”、“b_id”、“name”、“some_id”列。有什么方法可以为表B的列名加上前缀而不单独列出每一列吗?等价于这个:

SELECT a.*, b.b_id as 'b.b_id', b.name as 'b.name', b.some_id as 'b.some_id'
FROM TABLE_A a JOIN TABLE_B b USING (some_id);

但是,如前所述,没有列出每一列,所以像这样:

SELECT a.*, b.* as 'b.*'
FROM TABLE_A a JOIN TABLE_B b USING (some_id);

基本上就是说,“用‘something’为b.*返回的每一列添加前缀”。这可能吗,还是我运气不好?

编辑

关于不使用SELECT *等的建议是有效的建议,但与我的上下文无关,因此请关注眼前的问题——是否可以在连接中为表的所有列名添加前缀(SQL查询中指定的常量)?

我的最终目标是能够通过连接对两个表执行SELECT *操作,并且能够从结果集中获得的列的名称中分辨出哪些列来自表a,哪些列来自表b。同样,我不想单独列出列,我需要能够执行SELECT *操作。


当前回答

与非常好的“PHP (Wordpress)函数”相同的响应,但为CakePHP 4.3编码。 放在src/Controller/Component/MyUtilsComponent.php中

<?php

namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Datasource\ConnectionManager;

class MyUtilsComponent extends Component
{
    public static function prefixedTableFieldsWildcard(string $table, string $alias, string $connexion = 'default'): string
    {
        $c = ConnectionManager::get($connexion);
        $columns = $c->execute("SHOW COLUMNS FROM $table");
        $field_names = [];
        foreach ($columns as $column) {
            $field_names[] = $column['Field'];
        }

        $prefixed = [];
        foreach ($field_names as $field_name) {
            $prefixed[] = "`{$alias}`.`{$field_name}` AS `{$alias}.{$field_name}`";
        }
        return implode(', ', $prefixed);
    }
}

测试和使用

    function testPrefixedTableFieldsWildcard(): void
    {
        $fields = MyUtilsComponent::prefixedTableFieldsWildcard('metas', 'u', 'test');
        $this->assertEquals('`u`.`id` AS `u.id`, `u`.`meta_key` AS `u.meta_key`, `u`.`meta_value` AS `u.meta_value`, `u`.`meta_default` AS `u.meta_default`, `u`.`meta_desc` AS `u.meta_desc`', $fields,);
    }

其他回答

I see two possible situations here. First, you want to know if there is a SQL standard for this, that you can use in general regardless of the database. No, there is not. Second, you want to know with regard to a specific dbms product. Then you need to identify it. But I imagine the most likely answer is that you'll get back something like "a.id, b.id" since that's how you'd need to identify the columns in your SQL expression. And the easiest way to find out what the default is, is just to submit such a query and see what you get back. If you want to specify what prefix comes before the dot, you can use "SELECT * FROM a AS my_alias", for instance.

PHP 7.2 + MySQL/Mariadb

MySQL会给你发送多个相同名称的字段。甚至在终端客户端。但如果你想要一个关联数组,你必须自己创建键。

感谢@axelbrz的原创。我已经将它移植到更新的php,并对它进行了一些清理:

function mysqli_rows_with_columns($link, $query) {
    $result = mysqli_query($link, $query);
    if (!$result) {
        return mysqli_error($link);
    }
    $field_count = mysqli_num_fields($result);
    $fields = array();
    for ($i = 0; $i < $field_count; $i++) {
        $field = mysqli_fetch_field_direct($result, $i);
        $fields[] = $field->table . '.' . $field->name; # changed by AS
        #$fields[] = $field->orgtable . '.' . $field->orgname; # actual table/field names
    }
    $rows = array();
    while ($row = mysqli_fetch_row($result)) {
        $new_row = array();
        for ($i = 0; $i < $field_count; $i++) {
            $new_row[$fields[$i]] = $row[$i];
        }
        $rows[] = $new_row;
    }
    mysqli_free_result($result);
    return $rows;
}

$link = mysqli_connect('localhost', 'fixme', 'fixme', 'fixme');
print_r(mysqli_rows_with_columns($link, 'select foo.*, bar.* from foo, bar'));

我知道的唯一一个这样做的数据库是SQLite,这取决于你使用PRAGMA full_column_names和PRAGMA short_column_names配置的设置。参见http://www.sqlite.org/pragma.html

否则,如果在查询中键入列名对您来说太麻烦的话,我所能建议的是通过序号位置而不是通过列名来获取结果集中的列。

这是一个很好的例子,说明了为什么使用SELECT *是不好的做法——因为最终您还是需要输入所有列名。

我理解需要支持可能更改名称或位置的列,但使用通配符会使这变得更加困难,而不是更容易。

我和OP在同一条船上-我有来自3个不同表的数十个字段,我正在加入,其中一些具有相同的名称(即。身份证、姓名等)。我不想列出每个字段,所以我的解决方案是对共享名称的字段使用别名,并对具有唯一名称的字段使用select *。

例如:

表a: id, 的名字, field1, field2……

表b: id, 的名字, field3, field4……

选择a.id为aID, a.name为ame, a. *, b.id为bID, b.name为bName, b. * .....

当访问结果时,我们这些字段的别名和忽略“原始”名称。

也许不是最好的解决方案,但它为我工作....我用mysql

Select *通常会导致糟糕的代码,因为往往会添加新列,或者表中列的顺序经常改变,这通常会以非常微妙的方式破坏Select *。所以列出列是正确的解决方案。

至于如何进行查询,mysql不确定,但在sqlserver中,您可以从syscolumns中选择列名,并动态构建select子句。