我确信在连接中使用表名作为前缀和/或后缀字段名称的这种功能应该包含在ANSI SQL STANDARD中。目前,在 2019 年,仍然没有优雅的跨平台方式来做到这一点,剩下的就是使用别名的丑陋且容易出错的手动黑客,或涉及动态 sql 的特定于平台的解决方案。每个人都会真正受益于能够为“点星”(.*) 表示的字段指定自定义前缀或/和后缀。添加此类功能后的示例选择将是:
select a.* use prefix,b.* use postfix '_b' from table_a a inner join table_b b on a.id=b.id
如您所见,默认情况下前缀或后缀将等于表名(或别名),并且可以用任何所需的字符串文字覆盖。
还需要添加到标准中的是能够从“已加星标”(*) 输出中排除某些字段,这是选择所有字段的快捷方式。由于减少网络数据传输或/和简洁的原因,我将添加except关键字以列出我不想包含在内的字段,例如:
select * except large_binary_data_field,another_notneeded_field,etc from my_table
这样的特性将允许避免显式指定需要的完整(并且可能很大)字段列表的必要性,而不是仅指定星号和一些不需要的字段。
所以拜托,无论谁阅读了这篇文章并能够接触到 ANSI SQL 标准的影响者,你都知道该怎么做)
PS 又一个丑陋的,但至少是自动化和通用的动态 sql 包装器
对于使用 psycopg 的 Python 拥护者,这是我使用的方便的子程序(严格在内部,因为它很容易发生 sql 注入)
def get_table_fields(table,alias,prefix='',suffix='',excluding=''):
if type(excluding)==str: excluding=excluding.split(',')
cur.execute('select * from '+table+' where 0=1');cur.fetchall()
if not (cur.description is None):
return ','.join([alias+'.'+col.name+' '+prefix+col.name+suffix for col in cur.description if not (col.name in excluding)])
以及调用代码,我将在其中加入 3 个表并希望避免从数据集表中获取大数据字段:
sql="""select %s,%s,%s from tasks t,features_sets f,datasets d
where
t.is_active=true and f.is_active=true
and f.task=t.id and t.train_dataset=d.id
""" % (
get_table_fields('tasks','t',prefix='ts_'),
get_table_fields('features_sets','f',prefix='fs_'),
get_table_fields('datasets','d',prefix='ds_',excluding='data')
)
它为我展开成强大的
select t.id ts_id,t.project ts_project,t.name ts_name,***,
fs_id,f.task fs_task,f.name fs_name,f.description fs_description,***,
d.id ds_id,d.project ds_project,d.name ds_name,***
from tasks t,features_sets f,datasets d
where
t.is_active=true and f.is_active=true
and f.task=t.id and t.train_dataset=d.id
其中 *** 表示大量其他有用的字段,其中一些在多个表中很常见(因此需要前缀)。cur显然是 psycopg 游标,并且 0=1 条件旨在仅检索没有真实数据的字段名称。