From e7c56c28c91dc138b93c0b027f777be989268b10 Mon Sep 17 00:00:00 2001 From: Patrice Bender Date: Thu, 16 Apr 2026 15:23:33 +0200 Subject: [PATCH 1/5] docs: re-add paragraph about `ON DELETE CASCADE` this is an important distinction. Users open issues because they dont understand the feature scope, e.g. cap/issues/issues/20464 --- guides/databases/cdl-to-ddl.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/guides/databases/cdl-to-ddl.md b/guides/databases/cdl-to-ddl.md index b48ef4f7a2..15a9a3a6fa 100644 --- a/guides/databases/cdl-to-ddl.md +++ b/guides/databases/cdl-to-ddl.md @@ -613,6 +613,35 @@ CREATE TABLE Books ( ... > [!tip] Consider using @assert.target instead > Database constraints are meant to protect against data corruption due to programming errors. Prefer using the [`@assert.target`](../services/constraints#assert-target) for application-level input validation, which is more tuned for typical application scenarios, with error messages taylored for end users. +#### `ON DELETE CASCADE` + +From the example above it becomes clear that a book can still exist, even if its author is deleted. However, think of an existential relationship between a book and its pages: a page cannot exist without its book. In such cases, you would want the pages to be automatically deleted when the book (parent) is deleted. + +Typically such existential relationships are modeled in CDS using [compositions](../../cds/cdl#compositions). +That is why for managed **backlink** associations — those used in a composition's on-condition via `$self = .` +the foreign key constraints are generated with `ON DELETE CASCADE` by default, instead of `ON DELETE RESTRICT`: + +```cds +entity Books { + pages: Composition of many Pages on pages.book = $self; +} +entity Pages { + key number: Integer; + key book: Association to Books; // → ON DELETE CASCADE (backlink) +} +``` + +```sql +… +ALTER TABLE Pages ADD CONSTRAINT c__Pages_book + FOREIGN KEY(book_ID) REFERENCES Books(ID) + ON UPDATE RESTRICT + ON DELETE CASCADE + VALIDATED + ENFORCED + INITIALLY DEFERRED; +``` + #### Skipping with `@assert.integrity:false` You can skip foreign key constraint generation for specific associations by annotating them with `@assert.integrity:false`, for example: From 486736495c9bb527a973843f98f1691ec1db3ab3 Mon Sep 17 00:00:00 2001 From: Patrice Bender Date: Thu, 16 Apr 2026 15:32:45 +0200 Subject: [PATCH 2/5] convention --- guides/databases/cdl-to-ddl.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/guides/databases/cdl-to-ddl.md b/guides/databases/cdl-to-ddl.md index 15a9a3a6fa..691143ed71 100644 --- a/guides/databases/cdl-to-ddl.md +++ b/guides/databases/cdl-to-ddl.md @@ -615,23 +615,26 @@ CREATE TABLE Books ( ... #### `ON DELETE CASCADE` -From the example above it becomes clear that a book can still exist, even if its author is deleted. However, think of an existential relationship between a book and its pages: a page cannot exist without its book. In such cases, you would want the pages to be automatically deleted when the book (parent) is deleted. +Think of the example above: a book can still exist, even if its author is deleted. However, this may be different fo existential relationships like the one between a book and its pages: a page cannot exist without a corresponding book. In such cases, you would want the pages to be automatically deleted when the book (parent) is deleted. Typically such existential relationships are modeled in CDS using [compositions](../../cds/cdl#compositions). That is why for managed **backlink** associations — those used in a composition's on-condition via `$self = .` the foreign key constraints are generated with `ON DELETE CASCADE` by default, instead of `ON DELETE RESTRICT`: -```cds +::: code-group +```cds [CDS Source] entity Books { pages: Composition of many Pages on pages.book = $self; } entity Pages { key number: Integer; - key book: Association to Books; // → ON DELETE CASCADE (backlink) + key book: Association to Books; // → ON DELETE CASCADE } ``` +::: -```sql +::: code-group +```sql [=>   Generated DDL] … ALTER TABLE Pages ADD CONSTRAINT c__Pages_book FOREIGN KEY(book_ID) REFERENCES Books(ID) @@ -641,6 +644,7 @@ ALTER TABLE Pages ADD CONSTRAINT c__Pages_book ENFORCED INITIALLY DEFERRED; ``` +::: #### Skipping with `@assert.integrity:false` From 73cb7cdc2cda3bdbf8926aa4145d2d6901ec65e9 Mon Sep 17 00:00:00 2001 From: Patrice Bender Date: Fri, 17 Apr 2026 09:50:43 +0200 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Steffen Weinstock <79531202+stewsk@users.noreply.github.com> --- guides/databases/cdl-to-ddl.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/guides/databases/cdl-to-ddl.md b/guides/databases/cdl-to-ddl.md index 691143ed71..70a018b7f6 100644 --- a/guides/databases/cdl-to-ddl.md +++ b/guides/databases/cdl-to-ddl.md @@ -615,15 +615,16 @@ CREATE TABLE Books ( ... #### `ON DELETE CASCADE` -Think of the example above: a book can still exist, even if its author is deleted. However, this may be different fo existential relationships like the one between a book and its pages: a page cannot exist without a corresponding book. In such cases, you would want the pages to be automatically deleted when the book (parent) is deleted. +Think of the example above: a book can still exist, even if its author is deleted. However, this may be different for existential relationships like the one between a book and its pages: a page cannot exist without a corresponding book. In such cases, you would want the pages to be automatically deleted when the book (parent) is deleted. Typically such existential relationships are modeled in CDS using [compositions](../../cds/cdl#compositions). -That is why for managed **backlink** associations — those used in a composition's on-condition via `$self = .` +That is why for managed **backlink** associations — those used in a composition's on-condition via `$self = .` - the foreign key constraints are generated with `ON DELETE CASCADE` by default, instead of `ON DELETE RESTRICT`: ::: code-group ```cds [CDS Source] entity Books { + key ID : Integer; pages: Composition of many Pages on pages.book = $self; } entity Pages { From 780df5187c9f7e8814143db8568011aa4dfc2efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Jeglinsky?= Date: Mon, 20 Apr 2026 10:22:51 +0200 Subject: [PATCH 4/5] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- guides/databases/cdl-to-ddl.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/guides/databases/cdl-to-ddl.md b/guides/databases/cdl-to-ddl.md index 70a018b7f6..0c73a3c7bd 100644 --- a/guides/databases/cdl-to-ddl.md +++ b/guides/databases/cdl-to-ddl.md @@ -611,15 +611,14 @@ CREATE TABLE Books ( ... ::: > [!tip] Consider using @assert.target instead -> Database constraints are meant to protect against data corruption due to programming errors. Prefer using the [`@assert.target`](../services/constraints#assert-target) for application-level input validation, which is more tuned for typical application scenarios, with error messages taylored for end users. +> Database constraints are meant to protect against data corruption due to programming errors. Prefer using the [`@assert.target`](../services/constraints#assert-target) for application-level input validation, which is more tuned for typical application scenarios, with error messages tailored for end users. #### `ON DELETE CASCADE` -Think of the example above: a book can still exist, even if its author is deleted. However, this may be different for existential relationships like the one between a book and its pages: a page cannot exist without a corresponding book. In such cases, you would want the pages to be automatically deleted when the book (parent) is deleted. +Think of the example above: a book can still exist, even if its author is deleted. However, this differs for existential relationships like the one between a book and its pages: a page cannot exist without a corresponding book. In such cases, you want the pages to be automatically deleted when the book (parent) is deleted. Typically such existential relationships are modeled in CDS using [compositions](../../cds/cdl#compositions). -That is why for managed **backlink** associations — those used in a composition's on-condition via `$self = .` - -the foreign key constraints are generated with `ON DELETE CASCADE` by default, instead of `ON DELETE RESTRICT`: +That is why for managed **backlink** associations (those used in a composition's on-condition via `$self = .`), the foreign key constraints are generated with `ON DELETE CASCADE` by default, instead of `ON DELETE RESTRICT`: ::: code-group ```cds [CDS Source] From a26bc0684010a3fdf91464c200ba5decd5ebc9cc Mon Sep 17 00:00:00 2001 From: Patrice Bender Date: Tue, 28 Apr 2026 19:45:24 +0200 Subject: [PATCH 5/5] Update guides/databases/cdl-to-ddl.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- guides/databases/cdl-to-ddl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/databases/cdl-to-ddl.md b/guides/databases/cdl-to-ddl.md index 0c73a3c7bd..2c3f186e12 100644 --- a/guides/databases/cdl-to-ddl.md +++ b/guides/databases/cdl-to-ddl.md @@ -634,7 +634,7 @@ entity Pages { ::: ::: code-group -```sql [=>   Generated DDL] +```sql [=> Generated DDL] … ALTER TABLE Pages ADD CONSTRAINT c__Pages_book FOREIGN KEY(book_ID) REFERENCES Books(ID)