我想知道这在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字段存在时,它们能够独立地更新多表连接的每个表。

其他回答

如果关心模式变化,这可能对你有用: 1. 在所有涉及的表上运行'DESCRIBE table'查询。 2. 使用返回的字段名动态构造以所选别名为前缀的列名字符串。

问题的答案似乎是否定的,但是可以使用的一种方法是分配一个虚拟列来分隔每个新表。如果使用Python或PHP等脚本语言对列列表的结果集进行循环,那么这种方法尤其有效。

SELECT '' as table1_dummy, table1.*, '' as table2_dummy, table2.*, '' as table3_dummy, table3.* FROM table1
JOIN table2 ON table2.table1id = table1.id
JOIN table3 ON table3.table1id = table1.id

我知道这并不能完全回答您的问题,但是如果您是一名程序员,这是分离具有重复列名的表的好方法。

你可能会认为微软花了13年时间才把它装进去。它对于调试非常有用。 我已经养成了这样做的习惯:选择我认为我想要比较的列,然后在最后加上一个*来捕获我可能想要查看的任何其他内容。

选择a.breed, a.size, p.breed, p.size,a.,p。 源自动物 加入宠物p在a.breed=p.breed

不管怎样,你懂的。

我在PostgreSQL 13中使用to_jsonb函数来获得连接表中的所有字段作为一列。

select
  TABLE_A.*,
  to_jsonb(TABLE_B.*) as b,
  to_jsonb(TABLE_C.*) as c
from TABLE_A
left join TABLE_B on TABLE_B.a_id=TABLE_A.id
left join TABLE_C on TABLE_C.a_id=TABLE_A.id
where TABLE_A.id=1

结果你会得到TABLE_A列加上b和c列的数量:

id name some_other_col b c
1 Some name Some other value {"id":1,"a_id":1,"prop":"value"} {"id":1,"a_id":1,"prop":"value"}
1 Some other name Another value {"id":1,"a_id":1,"prop":"value"} {"id":1,"a_id":1,"prop":"value"}

您只需要解析b和c列以将它们转换为对象。

我完全理解您关于重复字段名的问题。

我也需要它,直到我编写了自己的函数来解决它。如果您正在使用PHP,您可以使用它,或者如果您有以下设施,则可以使用您正在使用的语言编写代码。

这里的技巧是mysql_field_table()返回表名,mysql_field_name()返回结果中每一行的字段(如果它是使用mysql_num_fields()获得的),这样您就可以将它们混合在一个新数组中。

这是所有列的前缀;)

问候,

function mysql_rows_with_columns($query) {
    $result = mysql_query($query);
    if (!$result) return false; // mysql_error() could be used outside
    $fields = mysql_num_fields($result);
    $rows = array();
    while ($row = mysql_fetch_row($result)) { 
        $newRow = array();
        for ($i=0; $i<$fields; $i++) {
            $table = mysql_field_table($result, $i);
            $name = mysql_field_name($result, $i);
            $newRow[$table . "." . $name] = $row[$i];
        }
        $rows[] = $newRow;
    }
    mysql_free_result($result);
    return $rows;
}