Waiting for SQL:202y: Stockholm (BMA) meeting report
摘要
会议于 2026 年 6 月 15-19 日在 Stockholm 举行,WG3 标准化 SQL 和 GQL。报道接受以下新 SQL 特性:QUALIFY 子句(窗口函数后过滤,如原提案举例,避免子查询包装);INSERT BY NAME 选项(SELECT 源匹配改为按名,默认按位置,可显式 BY POSITION);SELECT list EXCLUDE(扩展列排除及更多 postprocessing,已标准化,支持星号限定形式);JOIN TO ONE(运行时检查左表每行最多匹配右表一行,如预留记录对应多间房引发异常)。Key joins 提案获兴趣但未接受(语法检查时强制外键匹配)。PostgreSQL 19 QUALIFY 补丁因定义问题暂停,现已解决;SELECT list EXCLUDE 部分实现已开始。原计划 2026 年 10 月评论决议会议 + 2027 年中发布新标准,因 Key joins 又定 2026 年 8 月会商,发布时间可能推迟半年。原文链接为完整正文,含提案示例和细节。
荐读理由
接受了 QUALIFY 子句,可避免子查询包装,直接在窗口函数后筛选(已多方实现标准);接受了 SELECT list EXCLUDE 语法,可对 SELECT 扩展列精确排除;接受了 JOIN TO ONE 语法,可在运行时避免 JOIN 漏匹配导致异常;接受了 INSERT BY NAME 选项,可让 INSERT SELECT 按列名匹配而非位置。
原文
Waiting for SQL:202y: Stockholm (BMA) meeting report
The most recent meeting of ISO/IEC JTC1 SC32 WG3 “Database Languages” took place from the 15th to the 19th of June 2026 in Stockholm. “WG3”, as we call it, works on standardizing the database languages SQL and GQL. In that meeting, a number of proposals that are of interest to SQL and PostgreSQL were accepted, which I want to report about here.
The meeting code of this meeting was “BMA”, which is the code for a small airport in Stockholm. All in-person WG3 meetings are named after a nearby airport. In this case, the code “ARN” for Stockholm’s main airport had already been used for a meeting in 2003. (It is whimsically intentional that this system prevents the group from meeting in the same place too many times.)
Now let’s look at the new SQL features that were discussed. (Regards to all the GQL practitioners, but I’m not qualified enough to report on that.)
(Note that when I write below that something has been accepted into the standard, that means it’s now in a working draft. There is still a bit of a road until all of this is an approved actual standard.)
QUALIFY
The QUALIFY clause has been accepted into the standard. This clause is a filter like WHERE or HAVING but is applied after window functions. For example1:
SELECT product_name, category, price
FROM products
QUALIFY price > avg(price) OVER (PARTITION BY category);
Previously, you would have to do this filtering by wrapping the query in a subquery, like
SELECT product_name, category, price
FROM (
SELECT product_name, category, price,
avg(price) OVER (PARTITION BY category)
AS category_avg
FROM products
) AS q
WHERE q.price > q.category_avg
The QUALIFY clause is already a nonstandard extension in many SQL implementations. A patch for PostgreSQL was in progress for PostgreSQL 19, but it was paused because some definitional issues had to be resolved, which has now been done with the change proposal to the standard. So I think we can look forward to seeing progress on that for PostgreSQL 20.
INSERT BY NAME
The INSERT option BY NAME has been accepted into the standard. This is a nice little usability improvement when you use INSERT with a SELECT as the source. Up until now, you needed to match up the columns in the INSERT and the columns in the SELECT output by position, which is tedious. Often, it would be more intuitive to have them matched by name:
INSERT INTO t1 (c1, c2)
BY NAME
SELECT c1 * 10 AS c2, c2 + 5 AS c1 FROM t2 WHERE c1 < 5;
The BY NAME clause selects this new behavior. The matching by position remains the default, and you can now also write BY POSITION to call for it explicitly.
I don’t know of anyone working on this for PostgreSQL, but it could be a relatively simple project for someone to pick up.
SELECT list EXCLUDE
This is a change proposal paper that I presented. This allows excluding columns of the SELECT * expansion, and a few more things. This has now been accepted into the standard.
This was one of the top-three feature requests that I have been receiving over the years for the SQL standard.2
I first presented this change proposal at the Barcelona meeting in September 2025. In the ensuing discussion, some working group participants raised additional proposals for more star-expansion postprocessing features, so we postponed the adoption of my proposal at the time. I have since worked on consolidating the various additional ideas, which this is the result of.
So with the adoption of this paper, the following syntax has now been standardized:
SELECT * (EXCLUDE (a, b)
REPLACE (c WITH x+y, d WITH z*2)
RENAME (e AS ee, f AS foo))
FROM t ...
The qualified-asterisk variant
SELECT t.* (EXCLUDE ...) FROM t ...
is also supported.
Syntax similar to this already exists in a number of implementations, but I found there were a lot of inconsistencies and poorly defined or poorly documented behaviors. With this standardization, some of this could be improved.
A partial implementation for PostgreSQL was begun late in the PostgreSQL 19 cycle. I look forward to this being continued and hopefully concluded for PostgreSQL 20.
JOIN TO ONE
The JOIN TO ONE syntax has been accepted into the standard. This addition to the join syntax is meant to prevent some mistakes when writing join queries. It checks at run time that each row on the left side of the join is matched up against at most one row on the right side of the join. Consider this query:
SELECT ro.room_number, ro.room_type, ro.price, re.guest_name
FROM reservations re
INNER JOIN TO ONE rooms ro ON ro.room_number = re.room_number
WHERE re.id = 16354;
This will raise an exception if a reservations record is matched against more than one rooms record by the join. (Maybe the reason was, in this example, that the joins in the query were incomplete. Maybe you were supposed to also join against a hotels table; see example below.)
There was some debate about how helpful this feature is, especially in contrast to the topic in the next section below, but in the end there was consensus for adopting it into the standard. Maybe a topic for a separate article.
Work in progress: Key joins
The key joins proposal was presented and received a significant amount of interest but was not yet accepted. (It is a fairly large and complex proposal and will need further scrutiny and refinement.)
This is a different proposal to prevent mistakes in join queries. It proposes a new syntax that enforces at syntax checking time that the join condition corresponds to a foreign key constraint.
The above example query would be written as a key join like this (again, not accepted yet, could change):
SELECT ro.room_number, ro.room_type, ro.price, re.guest_name
FROM reservations AS re
JOIN rooms AS ro FOR KEY (room_number) <- re (room_number)
WHERE re.reservation_id = 16354;
This would check that a foreign key exists that matches the join condition, so something like
-- TABLE reservations
FOREIGN KEY (room_number) REFERENCES rooms (room_number)
To continue the example, maybe that foreign key doesn’t actually exist, and the real foreign key is
-- TABLE reservations
FOREIGN KEY (hotel_id, room_number) REFERENCES rooms (hotel_id, room_number)
and the correct query might be:
SELECT ro.room_type, ro.rate, re.guest_name
FROM reservations AS re
JOIN rooms AS ro FOR KEY (hotel_id, room_number) <- re (hotel_id, room_number)
WHERE re.reservation_id = 16354;
There is a proof-of-concept patch proposal for PostgreSQL. The authors also have their own web site for this proposal.
(I’m not directly involved in this work, but I have given feedback on several occasions.)
What’s next
The original plan was to have one more comment resolution meeting in October 2026 and then wrap things up with an eye toward publishing a new version of the SQL standard in the middle of 2027. (This also would have lined up nicely with the PostgreSQL 20 schedule.)
Because of the interest in the key joins work, another meeting has now been scheduled for August 2026 to be able to make progress on that proposal.
Also, some participants from both the SQL and the GQL camps have suggested that they may want to delay the publication schedule by perhaps half a year to be able to fit in some more strategically important work.
So altogether the schedule is a bit uncertain right now but I suppose we’ll get a clearer picture in August.
In the meantime, as I’m writing this, the PostgreSQL 20 development cycle is about to kick off, and this article contains some project ideas in various stages, if someone wants to chip in.
The examples in this article have been adopted from the respective change proposal papers. ↩
The other two being trailing commas and
GROUP BY ALL. ↩
这条对你有帮助吗?