select * from (select a,b,c ...) 结果列的保证顺序?
select * from (select a,b,c ...) guaranteed order of result columns?
我最近在代码审查中发表评论:
it's better to enumerate the fields explicitly. "select *" doesn't
guarantee an order
对于像 select * from (select a,b,c ...)
这样的查询,在这种情况下是这样吗?我无法想象一个数据库引擎会重新排序结果中的列,但我的想象比某些数据库引擎更合乎逻辑。
列始终按照 table 中定义的顺序排列。但是,如果没有包含 order by 子句,则行并不总是以相同的顺序获取。
针对 select *
的建议主要针对直接查询 table 的情况。
在某些数据库中,可以在 table 中途插入一个新列,这样 table t (a, b)
就变成了 table t (a, c, b)
。 PostgreSQL(还)不支持这一点,但它仍然可以追加列,并且可以从任何地方删除列,所以如果你添加 c
并删除 b
,你仍然可以获得 t (a, c)
。
这就是为什么在生产查询中使用 *
被认为是不好的做法,尤其是当您的应用程序依赖于序号列位置来读取结果时。但实际上,这仅适用于您未在查询中的其他地方指定字段的情况。
在你的情况下,你在子查询中这样做。所以 *
是绝对安全的,IMO 完全接受 table 这种用法。
这个:
select * from (select a,b,c ... from t)
很好。
这个:
select * from t
或
select * from (select * from t)
是有问题的,因为它们使应用程序未定义列顺序。即便如此,如果您的应用程序 假定 列顺序而不检查查询元数据,这只是一个问题。
就我个人而言,大多数时候我更喜欢完全限定我的专栏,但确实有时 *
是最易读的选项。
另外,IMO,当客户端应用程序按名称而不是序号读取列时,使用 select *
也很好。如果你的应用程序从不关心 c
是第 2 列还是第 3 列,因为它使用结果元数据来构建行字典(就像 Perl 的 DBI 或 Python 的 psycopg2 可以做的那样)那么没有真正的理由不要只使用 *
.
不过,当您只需要一部分列时,SELECT *
可能会产生性能成本。错失了使用仅索引扫描的机会,不必要地获取离线 TOAST 数据,以及因不需要的值而浪费的带宽等等。所以大多数时候它仍然不是一个好主意。
我最近在代码审查中发表评论:
it's better to enumerate the fields explicitly. "select *" doesn't guarantee an order
对于像 select * from (select a,b,c ...)
这样的查询,在这种情况下是这样吗?我无法想象一个数据库引擎会重新排序结果中的列,但我的想象比某些数据库引擎更合乎逻辑。
列始终按照 table 中定义的顺序排列。但是,如果没有包含 order by 子句,则行并不总是以相同的顺序获取。
针对 select *
的建议主要针对直接查询 table 的情况。
在某些数据库中,可以在 table 中途插入一个新列,这样 table t (a, b)
就变成了 table t (a, c, b)
。 PostgreSQL(还)不支持这一点,但它仍然可以追加列,并且可以从任何地方删除列,所以如果你添加 c
并删除 b
,你仍然可以获得 t (a, c)
。
这就是为什么在生产查询中使用 *
被认为是不好的做法,尤其是当您的应用程序依赖于序号列位置来读取结果时。但实际上,这仅适用于您未在查询中的其他地方指定字段的情况。
在你的情况下,你在子查询中这样做。所以 *
是绝对安全的,IMO 完全接受 table 这种用法。
这个:
select * from (select a,b,c ... from t)
很好。
这个:
select * from t
或
select * from (select * from t)
是有问题的,因为它们使应用程序未定义列顺序。即便如此,如果您的应用程序 假定 列顺序而不检查查询元数据,这只是一个问题。
就我个人而言,大多数时候我更喜欢完全限定我的专栏,但确实有时 *
是最易读的选项。
另外,IMO,当客户端应用程序按名称而不是序号读取列时,使用 select *
也很好。如果你的应用程序从不关心 c
是第 2 列还是第 3 列,因为它使用结果元数据来构建行字典(就像 Perl 的 DBI 或 Python 的 psycopg2 可以做的那样)那么没有真正的理由不要只使用 *
.
不过,当您只需要一部分列时,SELECT *
可能会产生性能成本。错失了使用仅索引扫描的机会,不必要地获取离线 TOAST 数据,以及因不需要的值而浪费的带宽等等。所以大多数时候它仍然不是一个好主意。