<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv" -->

---
title: Looking Forward to Postgres 19: Syntax Potpourri | daily.dev
description: Postgres 19 introduces three quality-of-life SQL syntax additions. First, ON CONFLICT DO SELECT enables true get-or-create semantics: it returns the existing...
canonical: https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Looking Forward to Postgres 19: Syntax Potpourri | daily.dev
og:description: Postgres 19 introduces three quality-of-life SQL syntax additions. First, ON CONFLICT DO SELECT enables true get-or-create semantics: it returns the existing...
og:url: https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv
og:image: https://api.daily.dev/og/posts/3r0ZiiEHV.png
og:image:alt: Looking Forward to Postgres 19: Syntax Potpourri
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Looking Forward to Postgres 19: Syntax Potpourri

**[Planet PostgreSQL](https://daily.dev/sources/planet-postgresql)** · 14 min read · 0 upvotes · 0 comments

## Summary

Postgres 19 introduces three quality-of-life SQL syntax additions. First, ON CONFLICT DO SELECT enables true get-or-create semantics: it returns the existing conflicting row rather than requiring a no-op update or getting nothing back from DO NOTHING. It supports row-level locking (FOR UPDATE, FOR SHARE, etc.) and an optional WHERE filter, but requires SELECT privilege and a RETURNING clause. Second, GROUP BY ALL automatically infers all non-aggregate, non-window-function columns from the SELECT list, eliminating the need to manually repeat column names. Third, COPY ... TO (FORMAT JSON) exports query results as newline-delimited JSON with proper type mapping — arrays become JSON arrays, jsonb columns nest as objects. A FORCE_ARRAY option wraps output in a valid JSON array for downstream parsers. COPY FROM JSON is not yet supported.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://postgr.es/p/9rN>

## Questions this post answers

### How do I return the existing row on a conflict in PostgreSQL instead of getting 0 rows from DO NOTHING?

Postgres 19 adds ON CONFLICT DO SELECT, which returns the existing conflicting row rather than nothing. Unlike DO NOTHING (which returns 0 rows) or the DO UPDATE no-op workaround (which causes a pointless write and tuple bloat), DO SELECT hands back the row already stored. A RETURNING clause is mandatory, and SELECT privilege on the table is required in addition to INSERT.

_Developers building get-or-create patterns in PostgreSQL track changes like this on daily.dev._

### How does GROUP BY ALL work in PostgreSQL 19?

GROUP BY ALL automatically infers every non-aggregate, non-window-function expression from the SELECT list as a grouping key, eliminating the need to repeat column names manually. Aggregates and window functions are excluded from the inferred grouping. If the SELECT list contains no aggregate or window function at all, GROUP BY ALL groups by every column, behaving like SELECT DISTINCT.

_PostgreSQL developers keeping up with query syntax changes find the latest coverage on daily.dev._

### How do I export PostgreSQL query results as JSON using COPY?

Postgres 19 adds FORMAT JSON to the COPY command. By default it emits newline-delimited JSON, one object per line, with arrays mapped to JSON arrays and jsonb columns nested as objects. Adding FORCE_ARRAY wraps the entire output in a valid JSON array suitable for JSON parsers. COPY FROM JSON is not yet supported — only export (TO) works.

_Teams replacing application-side data export logic with native PostgreSQL features follow releases like this on daily.dev._

## Similar posts on daily.dev

- [INSERT ... ON CONFLICT ... DO SELECT: a new feature in PostgreSQL v19](https://daily.dev/posts/insert-on-conflict-do-select-a-new-feature-in-postgresql-v19-nipree37c) · CYBERTEC PostgreSQL · 1 upvotes · 0 comments
- [Waiting for PostgreSQL 19 – json format for COPY TO – select \* from depesz;](https://daily.dev/posts/waiting-for-postgresql-19-json-format-for-copy-to-select-from-depesz--a8ry0nduu) · depesz · 0 upvotes · 0 comments
- [SQL Improvements in PostgreSQL 11–18: A Personal Selection](https://daily.dev/posts/sql-improvements-in-postgresql-11-18-a-personal-selection-hujlsgrj1) · Planet PostgreSQL · 0 upvotes · 0 comments
- [9 Advanced PostgreSQL Features I Wish I Knew Sooner](https://daily.dev/posts/9-advanced-postgresql-features-i-wish-i-knew-sooner-nezidnbnu) · marmelab · 115 upvotes · 0 comments
- [PostgreSQL 18 RETURNING Enhancements: A Game Changer for Modern Applications](https://daily.dev/posts/postgresql-18-returning-enhancements-a-game-changer-for-modern-applications-xrqrjxjua) · Lobsters · 51 upvotes · 1 comments

---

Tags: [#backend](https://daily.dev/tags/backend), [#sql](https://daily.dev/tags/sql), [#postgresql](https://daily.dev/tags/postgresql)

[View this post on daily.dev](https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Looking Forward to Postgres 19: Syntax Potpourri","url":"https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv"},"datePublished":"2026-08-07T12:02:45.112Z","dateModified":"2026-08-16T05:31:22.171Z","description":"Postgres 19 introduces three quality-of-life SQL syntax additions. First, ON CONFLICT DO SELECT enables true get-or-create semantics: it returns the existing...","image":"https://postgr.es/static/images/pgEdge-favicon.webp","thumbnailUrl":"https://postgr.es/static/images/pgEdge-favicon.webp","isAccessibleForFree":true,"articleSection":"Planet PostgreSQL","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Planet PostgreSQL","logo":"https://media.daily.dev/image/upload/logos/placeholder.jpg","url":"https://daily.dev/sources/planet-postgresql"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"backend,sql,postgresql","timeRequired":"PT14M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Planet PostgreSQL","item":"https://daily.dev/sources/planet-postgresql"},{"@type":"ListItem","position":3,"name":"Looking Forward to Postgres 19: Syntax Potpourri"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/looking-forward-to-postgres-19-syntax-potpourri-3r0ziiehv#faq","mainEntity":[{"@type":"Question","name":"How do I return the existing row on a conflict in PostgreSQL instead of getting 0 rows from DO NOTHING?","acceptedAnswer":{"@type":"Answer","text":"Postgres 19 adds ON CONFLICT DO SELECT, which returns the existing conflicting row rather than nothing. Unlike DO NOTHING (which returns 0 rows) or the DO UPDATE no-op workaround (which causes a pointless write and tuple bloat), DO SELECT hands back the row already stored. A RETURNING clause is mandatory, and SELECT privilege on the table is required in addition to INSERT. Developers building get-or-create patterns in PostgreSQL track changes like this on daily.dev."}},{"@type":"Question","name":"How does GROUP BY ALL work in PostgreSQL 19?","acceptedAnswer":{"@type":"Answer","text":"GROUP BY ALL automatically infers every non-aggregate, non-window-function expression from the SELECT list as a grouping key, eliminating the need to repeat column names manually. Aggregates and window functions are excluded from the inferred grouping. If the SELECT list contains no aggregate or window function at all, GROUP BY ALL groups by every column, behaving like SELECT DISTINCT. PostgreSQL developers keeping up with query syntax changes find the latest coverage on daily.dev."}},{"@type":"Question","name":"How do I export PostgreSQL query results as JSON using COPY?","acceptedAnswer":{"@type":"Answer","text":"Postgres 19 adds FORMAT JSON to the COPY command. By default it emits newline-delimited JSON, one object per line, with arrays mapped to JSON arrays and jsonb columns nested as objects. Adding FORCE_ARRAY wraps the entire output in a valid JSON array suitable for JSON parsers. COPY FROM JSON is not yet supported — only export (TO) works. Teams replacing application-side data export logic with native PostgreSQL features follow releases like this on daily.dev."}}]}
```

