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


当前回答

问题的答案似乎是否定的,但是可以使用的一种方法是分配一个虚拟列来分隔每个新表。如果使用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

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

其他回答

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

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

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

我和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

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

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

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

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

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

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

不管怎样,你懂的。

我根据答案实现了一个解决方案,建议在节点中使用虚拟或哨兵列。你可以通过生成SQL来使用它:

select 
    s.*
  , '' as _prefix__creator_
  , u.*
  , '' as _prefix__speaker_
  , p.*
from statements s 
  left join users u on s.creator_user_id = u.user_id
  left join persons p on s.speaker_person_id = p.person_id

然后对从数据库驱动程序返回的行进行后处理,比如addPrefixes(row)。

实现(基于我的驱动程序返回的字段/行,但应该很容易为其他DB驱动程序更改):

const PREFIX_INDICATOR = '_prefix__'
const STOP_PREFIX_INDICATOR = '_stop_prefix'

/** Adds a <prefix> to all properties that follow a property with the name: PREFIX_INDICATOR<prefix> */
function addPrefixes(fields, row) {
  let prefix = null
  for (const field of fields) {
    const key = field.name
    if (key.startsWith(PREFIX_INDICATOR)) {
      if (row[key] !== '') {
        throw new Error(`PREFIX_INDICATOR ${PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = key.substr(PREFIX_INDICATOR.length)
      delete row[key]
    } else if (key === STOP_PREFIX_INDICATOR) {
      if (row[key] !== '') {
        throw new Error(`STOP_PREFIX_INDICATOR ${STOP_PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = null
      delete row[key]
    } else if (prefix) {
      const prefixedKey = prefix + key
      row[prefixedKey] = row[key]
      delete row[key]
    }
  }
  return row
}

测试:

const {
  addPrefixes,
  PREFIX_INDICATOR,
  STOP_PREFIX_INDICATOR,
} = require('./BaseDao')

describe('addPrefixes', () => {
  test('adds prefixes', () => {
    const fields = [
      {name: 'id'},
      {name: PREFIX_INDICATOR + 'my_prefix_'},
      {name: 'foo'},
      {name: STOP_PREFIX_INDICATOR},
      {name: 'baz'},
    ]
    const row = {
      id: 1,
      [PREFIX_INDICATOR + 'my_prefix_']: '',
      foo: 'bar',
      [STOP_PREFIX_INDICATOR]: '',
      baz: 'spaz'
    }
    const expected = {
      id: 1,
      my_prefix_foo: 'bar',
      baz: 'spaz',
    }
    expect(addPrefixes(fields, row)).toEqual(expected)
  })
})