Waiting for SQL:202y: Stockholm (BMA) meeting report | Peter Eisentraut
The most recent meeting of ISO/IEC JTC1 SC32 WG3 “Database Languages”<br>took place from the 15th to the 19th of June 2026 in Stockholm.<br>“WG3”, as we call it, works on standardizing the database languages<br>SQL and GQL. In that meeting, a number of proposals that are of<br>interest to SQL and PostgreSQL were accepted, which I want to report<br>about here.
The meeting code of this meeting was “BMA”, which is the code for a<br>small airport in Stockholm. All in-person WG3 meetings are named<br>after a nearby airport. In this case, the code “ARN” for Stockholm’s<br>main airport had already been used for a meeting in 2003. (It is<br>whimsically intentional that this system prevents the group from<br>meeting in the same place too many times.)
Now let’s look at the new SQL features that were discussed. (Regards<br>to all the GQL practitioners, but I’m not qualified enough to report<br>on that.)
(Note that when I write below that something has been accepted into<br>the standard, that means it’s now in a working draft. There is still<br>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<br>is a filter like WHERE or HAVING but is applied after window<br>functions. For example1:
SELECT product_name, category, price<br>FROM products<br>QUALIFY price > avg(price) OVER (PARTITION BY category);
Previously, you would have to do this filtering by wrapping the query<br>in a subquery, like
SELECT product_name, category, price<br>FROM (<br>SELECT product_name, category, price,<br>avg(price) OVER (PARTITION BY category)<br>AS category_avg<br>FROM products<br>) AS q<br>WHERE q.price > q.category_avg
The QUALIFY clause is already a nonstandard extension in many SQL<br>implementations. A patch for PostgreSQL was in<br>progress<br>for PostgreSQL 19, but it was paused because some definitional issues<br>had to be resolved, which has now been done with the change proposal<br>to the standard. So I think we can look forward to seeing progress on<br>that for PostgreSQL 20.
INSERT BY NAME
The INSERT option BY NAME has been accepted into the standard.<br>This is a nice little usability improvement when you use INSERT with<br>a SELECT as the source. Up until now, you needed to match up the<br>columns in the INSERT and the columns in the SELECT output by<br>position, which is tedious. Often, it would be more intuitive to have<br>them matched by name:
INSERT INTO t1 (c1, c2)<br>BY NAME<br>SELECT c1 * 10 AS c2, c2 + 5 AS c1 FROM t2 WHERE c1
The BY NAME clause selects this new behavior. The matching by<br>position remains the default, and you can now also write BY POSITION<br>to call for it explicitly.
I don’t know of anyone working on this for PostgreSQL, but it could be<br>a relatively simple project for someone to pick up.
SELECT list EXCLUDE
This is a change proposal paper that I presented. This allows<br>excluding columns of the SELECT * expansion, and a few more things.<br>This has now been accepted into the standard.
This was one of the top-three feature requests that I have been<br>receiving over the years for the SQL standard.2
I first presented this change proposal at the Barcelona meeting in<br>September 2025. In the ensuing discussion, some working group<br>participants raised additional proposals for more star-expansion<br>postprocessing features, so we postponed the adoption of my proposal<br>at the time. I have since worked on consolidating the various<br>additional ideas, which this is the result of.
So with the adoption of this paper, the following syntax has now been<br>standardized:
SELECT * (EXCLUDE (a, b)<br>REPLACE (c WITH x+y, d WITH z*2)<br>RENAME (e AS ee, f AS foo))<br>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,<br>but I found there were a lot of inconsistencies and poorly defined or<br>poorly documented behaviors. With this standardization, some of this<br>could be improved.
A partial<br>implementation<br>for PostgreSQL was begun late in the PostgreSQL 19 cycle. I look<br>forward to this being continued and hopefully concluded for PostgreSQL<br>20.
JOIN TO ONE
The JOIN TO ONE syntax has been accepted into the standard. This<br>addition to the join syntax is meant to prevent some mistakes when<br>writing join queries. It checks at run time that each row on the<br>left side of the join is matched up against at most one row on the<br>right side of the join. Consider this query:
SELECT ro.room_number, ro.room_type, ro.price, re.guest_name<br>FROM reservations re<br>INNER JOIN TO ONE rooms ro ON ro.room_number = re.room_number<br>WHERE re.id = 16354;
This will raise an exception if a reservations record is matched<br>against more than one rooms record by the join. (Maybe the reason<br>was, in this example, that the joins in the query were incomplete.<br>Maybe you were supposed to also join against a hotels table; see<br>example below.)
There was some debate about how helpful this feature is, especially in<br>contrast...