我想知道这在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 *操作。


当前回答

对于使用MySQL C-API的人来说,你的问题有一个直接的答案。

给定SQL:

  SELECT a.*, b.*, c.* FROM table_a a JOIN table_b b USING (x) JOIN table_c c USING (y)

'mysql_stmt_result_metadata()'的结果将准备好的SQL查询中的字段定义提供到结构MYSQL_FIELD[]中。每个字段包含以下数据:

  char *name;                 /* Name of column (may be the alias) */
  char *org_name;             /* Original column name, if an alias */
  char *table;                /* Table of column if column was a field */
  char *org_table;            /* Org table name, if table was an alias */
  char *db;                   /* Database for table */
  char *catalog;              /* Catalog for table */
  char *def;                  /* Default value (set by mysql_list_fields) */
  unsigned long length;       /* Width of column (create length) */
  unsigned long max_length;   /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */

请注意以下字段:catalog、table、org_name

现在您知道SQL中的哪个字段属于哪个模式(即目录)和表。 这足以从多表sql查询中通用地识别每个字段,而不需要别名。

一个实际的产品SqlYOG在这样一个庄园中使用这个确切的数据,当PK字段存在时,它们能够独立地更新多表连接的每个表。

其他回答

在postgres中,我使用json函数来返回json对象.... 然后,在查询之后,我json_decode带有_json后缀的字段。

IE:

select row_to_json(tab1.*) AS tab1_json, row_to_json(tab2.*) AS tab2_json 
 from tab1
 join tab2 on tab2.t1id=tab1.id

然后在PHP(或任何其他语言),我循环通过返回的列和json_decode()他们,如果他们有“_json”后缀(也删除后缀。最后,我得到一个包含所有tab1字段的名为“tab1”的对象,以及一个包含所有tab2字段的名为“tab2”的对象。

通过重命名相关表中的字段,我解决了自己的一个类似问题。是的,我有这样做的特权,我知道可能不是每个人都有。我在表示表名的表中的每个字段中添加了前缀。因此,OP发布的SQL将保持不变

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

并且仍然给出了预期的结果——易于识别输出字段属于哪个表。

不同的数据库产品会给你不同的答案;但如果你走得太远,你是在自讨苦吃。您最好选择您想要的列,并为它们提供自己的别名,以便每个列的标识非常清晰,并且可以在结果中区分它们。

这将创建具有给定前缀的字段列表

select
    name + ' as prefix.' + name + ','
from sys.columns where object_id = object_id('mytable')
order by column_id

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'));