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


当前回答

或者你可以使用Red Gate SQL Refactor或SQL Prompt,它通过单击Tab按钮将SELECT *展开为列列表

所以在你的例子中,如果你输入SELECT * FROM A JOIN B… 转到*的末尾,Tab键,瞧!你会看到 选择a . columnn1, A.column2, ...., B. columnn1, B.column2 FROM A JOIN

但它不是免费的

其他回答

我所做的就是用Excel来连接这个过程。例如,首先我选择*并获取所有列,将它们粘贴到Excel中。然后写出环绕该列所需的代码。说我需要在一堆专栏前做广告。我有我的字段在a列和“作为prev_”在列B和我的字段再次在列c。在列d,我有一列。

然后在列e中使用concatanate,并将它们合并在一起,确保包含空格。然后将其剪切并粘贴到sql代码中。我还使用这种方法为相同的字段和其他更长的代码做case语句,我需要为数百个字段表中的每个字段做。

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

这个问题在实践中很有用。在软件编程中,只需要列出所有显式列,在这些列中,您需要特别小心地处理所有条件。

想象一下,当调试或尝试使用DBMS作为日常办公工具,而不是特定程序员的抽象底层基础设施的可变实现时,我们需要编写大量的sql。这种场景随处可见,比如数据库转换、迁移、管理等。这些sql大多只执行一次,不会再使用,给每个列名只是浪费时间。不要忘记SQL的发明不仅仅是为程序员使用的。

通常我会创建一个带列名前缀的实用程序视图,这里是pl/pgsql中的函数,这并不容易,但你可以将它转换为其他过程语言。

-- Create alias-view for specific table.

create or replace function mkaview(schema varchar, tab varchar, prefix varchar)
    returns table(orig varchar, alias varchar) as $$
declare
    qtab varchar;
    qview varchar;
    qcol varchar;
    qacol varchar;
    v record;
    sql varchar;
    len int;
begin
    qtab := '"' || schema || '"."' || tab || '"';
    qview := '"' || schema || '"."av' || prefix || tab || '"';
    sql := 'create view ' || qview || ' as select';

    for v in select * from information_schema.columns
            where table_schema = schema and table_name = tab
    loop
        qcol := '"' || v.column_name || '"';
        qacol := '"' || prefix || v.column_name || '"';

        sql := sql || ' ' || qcol || ' as ' || qacol;
        sql := sql || ', ';

        return query select qcol::varchar, qacol::varchar;
    end loop;

    len := length(sql);
    sql := left(sql, len - 2); -- trim the trailing ', '.
    sql := sql || ' from ' || qtab;

    raise info 'Execute SQL: %', sql;
    execute sql;
end
$$ language plpgsql;

例子:

-- This will create a view "avp_person" with "p_" prefix to all column names.
select * from mkaview('public', 'person', 'p_');

select * from avp_person;

对此没有SQL标准。

然而,通过代码生成(在表创建或修改或运行时按需生成),你可以很容易地做到这一点:

CREATE TABLE [dbo].[stackoverflow_329931_a](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [col2] [nchar](10) NULL,
    [col3] [nchar](10) NULL,
    [col4] [nchar](10) NULL,
 CONSTRAINT [PK_stackoverflow_329931_a] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[stackoverflow_329931_b](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [col2] [nchar](10) NULL,
    [col3] [nchar](10) NULL,
    [col4] [nchar](10) NULL,
 CONSTRAINT [PK_stackoverflow_329931_b] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

DECLARE @table1_name AS varchar(255)
DECLARE @table1_prefix AS varchar(255)
DECLARE @table2_name AS varchar(255)
DECLARE @table2_prefix AS varchar(255)
DECLARE @join_condition AS varchar(255)
SET @table1_name = 'stackoverflow_329931_a'
SET @table1_prefix = 'a_'
SET @table2_name = 'stackoverflow_329931_b'
SET @table2_prefix = 'b_'
SET @join_condition = 'a.[id] = b.[id]'

DECLARE @CRLF AS varchar(2)
SET @CRLF = CHAR(13) + CHAR(10)

DECLARE @a_columnlist AS varchar(MAX)
DECLARE @b_columnlist AS varchar(MAX)
DECLARE @sql AS varchar(MAX)

SELECT @a_columnlist = COALESCE(@a_columnlist + @CRLF + ',', '') + 'a.[' + COLUMN_NAME + '] AS [' + @table1_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table1_name
ORDER BY ORDINAL_POSITION

SELECT @b_columnlist = COALESCE(@b_columnlist + @CRLF + ',', '') + 'b.[' + COLUMN_NAME + '] AS [' + @table2_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table2_name
ORDER BY ORDINAL_POSITION

SET @sql = 'SELECT ' + @a_columnlist + '
,' + @b_columnlist + '
FROM [' + @table1_name + '] AS a
INNER JOIN [' + @table2_name + '] AS b
ON (' + @join_condition + ')'

PRINT @sql
-- EXEC (@sql)

我在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列以将它们转换为对象。