urQL/docs/11-merge.md

243 lines
11 KiB
Markdown
Raw Permalink Normal View History

2023-01-05 21:25:45 +03:00
# MERGE
2024-01-22 00:50:35 +03:00
*supported in urQL parser, not yet supported in Obelisk*
*some experimental stuff proposed here, take with a grain of salt*
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
`MERGE` is a statement that conditionally performs `INSERT`, `UPDATE`, or `DELETE` operations. It modifies the content of the `<target-table>`, merging data from the `<source-table>` and static `<common-table-expression>` sources.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
First, the MERGE command performs an outer join from `<target-table>` to `<source-table>` using `ON <merge-predicate>` producing candidate change rows.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
For each candidate change row, the `MATCHED` or `NOT MATCHED` status is determined. If applicable, `NOT MATCHED` on `<target-table>` or `<source-table>` is set.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
Finally, for each candidate change row, the first `WHEN` clause under the applicable `MATCHED`/`NOT MATCHED` condition is executed.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
A `WHEN` clause without `AND <predicate>` implies unconditional execution. Subsequent `WHEN` clauses for the same target/source matching condition are not allowed.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
If no `WHEN` clause evaluates as true, the target row remains unchanged, which is equivalent to specifying `NOP`.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
`MERGE` actions have the same effect as the standard `UPDATE`, `INSERT`, or `DELETE` commands.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
`MERGE` can update the contents of an existing target `<table>`, produce a new `<table>`, or produce a new virtual `<table-set>`.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
When `MERGE INTO` is specified or implied, `<target-table>` must be a base `<table>` and contents are updated in place. `PRODUCING NEW` may not be specified.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
When `MERGE FROM` is specified, `PRODUCING NEW` must also be specified. `<target-table>` can be a base `<table>` or any virtual table (i.e. `<view>` or `PASS-THRU` `<table-set>`).
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
If `<new-table>` is specified, it will be created as a new `<table>` and populated in the same way as when `<target-table>` is updated with `MERGE INTO`.
2022-08-06 17:06:18 +03:00
2023-05-29 23:31:01 +03:00
The output `<table-set>`'s row type will correspond to the row type of `<target-table>`. And its primary index (in the case when `<new-table>` is produced) will correspond to the primary index of `<target-table>`. The `<target-table>`'s `<foreign-key>`s are not replicated.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
If the resulting virtual-table row type is a union type, then the output must be a virtual-table `PASS-THRU`, not an update to `<target-table>` or creation of `<new-table>` as base `<table>`.
2023-05-12 00:30:15 +03:00
2024-04-28 19:22:56 +03:00
```
2023-05-25 05:33:27 +03:00
<merge> ::=
MERGE [ { INTO | FROM } ] <target-table> [ [ AS ] <alias> ]
2023-05-29 23:31:01 +03:00
[ PRODUCING NEW <new-table> ]
2023-05-25 05:33:27 +03:00
USING <source-table> [ [ AS ] <alias> ]
[ [ SCALAR ] [ ,...n ] ]
[ ON <merge-predicate> ]
[ WHEN MATCHED [ AND <matched-predicate> ]
THEN <merge-matched> ] [ ...n ]
[ WHEN NOT MATCHED [ BY TARGET ] [ AND <unmatched-target-predicate> ]
THEN <merge-not-matched> ] [ ...n ]
[ WHEN NOT MATCHED BY SOURCE [ AND <unmatched-source-predicate> ]
THEN <merge-matched> ] [ ...n ]
2024-01-22 00:50:35 +03:00
[ <as-of-time> ]
2024-04-28 19:22:56 +03:00
```
2022-08-10 23:23:12 +03:00
2024-04-28 19:22:56 +03:00
```
2023-05-15 17:39:13 +03:00
<target-table> ::= <table-set>
<new-table> ::= <table-set>
<source-table> ::= <table-set>
2023-05-12 00:30:15 +03:00
<matched-predicate> ::= <predicate>
<unmatched-target-predicate> ::= <predicate>
<unmatched-source-predicate> ::= <predicate>
2024-04-28 19:22:56 +03:00
```
2023-04-12 21:20:04 +03:00
2024-04-28 19:22:56 +03:00
```
2022-08-10 23:23:12 +03:00
<merge-matched> ::=
2023-04-12 21:20:04 +03:00
{ UPDATE [ SET ] { <column> = <scalar-expression> } [ ,...n ]
| DELETE
2023-05-12 00:30:15 +03:00
| NOP
2023-04-12 21:20:04 +03:00
}
2024-04-28 19:22:56 +03:00
```
2022-08-10 23:23:12 +03:00
2023-05-29 23:31:01 +03:00
Specifies the update or delete action that is applied to all rows of `<target-table>` that don't match the rows returned by `<table-source>` ON `<merge-predicate>`, and which satisfy any additional predicate.
**`<column>`**
Identifies column in `<target-table>`. Each column may be referenced once.
**`<scalar-expression>`**
Aura must match corresponding aura in `<target-table>`.
**DELETE**
Delete the matched target row.
**NOP**
No operation performed.
2024-04-28 19:22:56 +03:00
```
2022-08-10 23:23:12 +03:00
<merge-not-matched> ::=
2023-04-12 21:20:04 +03:00
INSERT [ ( <column> [ ,...n ] ) ]
2023-03-05 01:51:02 +03:00
VALUES ( <scalar-expression> [ ,...n ] )
2023-05-12 00:30:15 +03:00
| NOP
2024-04-28 19:22:56 +03:00
```
2022-08-10 21:45:17 +03:00
2023-05-29 23:31:01 +03:00
**`<column>`**
Identifies column in `<target-table>`. Each column may be referenced once.
**`<scalar-expression>`**
Aura must match corresponding aura in `<target-table>`.
The count out `INSERT` columns and `VALUES` must match.
**NOP**
No operation performed.
2024-01-22 00:50:35 +03:00
### API
2024-04-28 19:22:56 +03:00
```
2023-05-22 07:24:31 +03:00
+$ merge
$:
%merge
target-table=table-set
new-table=(unit table-set)
source-table=table-set
predicate=predicate
matched=(list matching)
unmatched-by-target=(list matching)
unmatched-by-source=(list matching)
2024-01-22 00:50:35 +03:00
as-of=(unit as-of)
2023-05-22 07:24:31 +03:00
==
2024-04-28 19:22:56 +03:00
```
2023-05-22 07:24:31 +03:00
2024-01-22 00:50:35 +03:00
### Arguments
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
**`[ { INTO | FROM } ] <target-table> [ [ AS ] <alias> ]`**
`<alias>` is alternative name to reference `<target-table>` in `WHEN` clauses and predicates.
If `{ INTO | FROM }` is not specified, `INTO` is the default.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If `INTO` is specified (or implied) then `<target-table>` is a base-table
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If `<target-table>` is a virtual-table -- any `<table-set>` other than a base-table, i.e. qualified `<view>`, `<common-table-expression>`, `*`, or `( column-1 [,...column-n] )` -- then `FROM` is required.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
`INTO` must not accompany `PRODUCING NEW` argument.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
`FROM` must accompany `PRODUCING NEW` argument.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
`<target-table>` is the table, view, or CTE against which the data rows from `<table-source>` are matched based on `<merge-predicate>`.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If `FROM` is specified, any `INSERT`, `UPDATE`, or `DELETE` operations specified by the `WHEN` clauses, as well as matched but otherwise unaffected target table rows, produce a new `<table-set>` as specified by the `PRODUCING NEW` clause.
**`[ PRODUCING NEW <new-table>` ]**
Required when `FROM` is specified.
Prohibited when `INTO` is specified or implied.
If `<new-table>` has the syntax of a qualified `<table>`, it cannot already exist.
If `<target-table>` has a row type which is a union type, `<new-table>` cannot be a base `<table>`.
**`USING <source-table> [ [ AS ] <alias> ]`**
Specifies the data source that is matched with the data rows in `<target-table>` joining on `<merge-predicate>`. `<table-source>` can be any `<table-set>`.
`<alias>` is an alternative name to reference `<source-table>` in `WHEN` clauses and predicates.
2023-04-12 21:20:04 +03:00
2023-05-29 04:47:58 +03:00
**`[ [ SCALAR ] [ ,...n ] ]`**
2023-05-12 00:30:15 +03:00
TBD
2023-04-12 21:20:04 +03:00
2023-05-29 04:47:58 +03:00
**`ON <merge-predicate>`**
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
Specifies the conditions on which `<table-source>` joins with `<target-table>`, determining the matching and can be any valid `<predicate>` not resulting in cartesian join.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
If `<merge-predicate>` is not specified, source and target must share row type and matching implies rows equal by value.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If `<merge-predicate>` does not resolve for any row sub-type between the target and source it potentially creates `NOT MATCHED` conditions `BY TARGET` and `BY SOURCE` on rows that otherwise are equal by value.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
**`[ WHEN MATCHED [ AND <target-predicate> ] THEN <merge-matched> ] [ ...n ]`**
Specifies that all rows of `<target-table>`, which join the rows returned by `<table-source>` ON `<merge-predicate>` or the implied join when `ON` predicate not present, and satisfy `<target-predicate>` (when present), result in some action according to the `<merge-matched>` clause.
2023-05-29 04:47:58 +03:00
2023-05-29 23:31:01 +03:00
`WHEN MATCHED` clause without `AND <matched-predicate>` implies unconditionally apply the `<merge-matched>` action.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If two or more `WHEN MATCHED` clauses are specified only the last clause may be unaccompanied by `AND <matched-predicate>`.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
The first `<matched-predicate>` evaluating to true determines the `<merge-matched>` action.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If there is no unconditional `<merge-matched>` action, it is the same as specifying `NOP` for unconditional action.
2023-05-29 04:47:58 +03:00
2023-05-29 23:31:01 +03:00
**`[ WHEN NOT MATCHED [ BY TARGET ] [ AND <unmatched-target-predicate> ] THEN <merge-not-matched> ] [ ...n ]`**
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
Specifies the action on `<target-table>` for every row returned by `<table-source>` ON `<merge-predicate>` that doesn't match a row in target-table, but satisfies `<unmatched-target-predicate>`, if present. The action to take is specified by the `<merge-not-matched>` clause.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
`WHEN NOT MATCHED BY TARGET` clause without `AND <unmatched-target-predicate>` implies unconditionally apply the `<merge-not-matched>` action.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If two or more `WHEN NOT MATCHED BY TARGET` clauses are specified only the last clause may be unaccompanied by `AND <unmatched-target-predicate>`.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
The first `<unmatched-target-predicate>` evaluating to true determines the `<merge-not-matched>` action.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If there is no unconditional `<merge-not-matched>` action, it is the same as specifying `NOP` for unconditional action.
2023-05-12 00:30:15 +03:00
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
**`WHEN NOT MATCHED BY SOURCE [ AND <unmatched-source-predicate> ] THEN <merge-matched>`**
2023-04-12 21:20:04 +03:00
2024-01-22 00:50:35 +03:00
Specifies that all rows of `<target-table>`, which don't match the rows returned by `<table-source>` ON `<merge-predicate>`, and that satisfy any additional search condition, are updated or deleted according to the `<merge-matched>` clause.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
`WHEN NOT MATCHED BY SOURCE` clause without `AND <unmatched-source-predicate>` implies unconditionally apply the `<merge-matched>` action.
2023-05-12 00:30:15 +03:00
2023-05-29 23:31:01 +03:00
If two or more `WHEN NOT MATCHED BY SOURCE` clauses are specified only the last clause may be unaccompanied by `AND <unmatched-source-predicate>`.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
The first `<unmatched-source-predicate>` evaluating to true determines the `<merge-matched>` action.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
If there is no unconditional `<merge-matched>` action, it is the same as specifying `NOP` for unconditional action.
2023-04-12 21:20:04 +03:00
2023-05-29 23:31:01 +03:00
When no rows are returned by `<table-source>`, columns in the source table can't be accessed, and therefore the `<merge-matched>` action cannot reference columns in `<table-source>`.
2023-04-12 21:20:04 +03:00
2024-01-22 00:50:35 +03:00
### Remarks
2023-05-29 23:31:01 +03:00
When `<target-table>` is updated in place or `<new-table>` specified as a base `<table>`, the command potentially results in a state change of the Obelisk agent.
Cross ship merges are not allowed.
In the case of multiple `WHEN MATCHED` or `WHEN NOT MATCHED` and overlapping predicates, the cases are processed in order, so the first successful case takes precedence.
2023-05-06 21:05:12 +03:00
Tables in the namespace *sys* cannot be merged into.
2023-05-29 23:31:01 +03:00
At least one of the three `MATCHED` / `NOT MATCHED` clauses must be specified, but they can be specified in any order.
`INSERT`, `UPDATE`, or `DELETE` actions specified on `<target-table>` are limited by any constraints defined on it (when it is a base `<table>`), including unique indices and any cascading referential integrity constraints.
2023-04-12 21:20:04 +03:00
2024-01-22 00:50:35 +03:00
It `<target-table>` is updated in place, or a `<new-table>` created, every `INSERT` clause must account for all columns in `<target-table>`. Inserting fewer columns results in a new row sub-type, which is allowed when creating a virtual `<table-set>`.
2023-05-29 23:31:01 +03:00
Any `<binary-operator>` referencing a column each from `<target-table>` and `<source-table>` satisfies the requirement that `ON <merge-predicate>` not produce a cartesian join. However, it is to be noted a cartestian join cannot be entirely prevented depending on column contents.
2023-04-12 21:20:04 +03:00
2024-01-22 00:50:35 +03:00
### Produced Metadata
2023-04-12 21:20:04 +03:00
2023-05-29 04:47:58 +03:00
`@@ROWCOUNT` returns the total number of rows [inserted=@ud updated=@ud deleted=@ud].
2023-04-12 21:20:04 +03:00
2024-01-22 00:50:35 +03:00
### Exceptions
2023-05-12 00:30:15 +03:00
`<target-table>` does not exist
`GRANT` permission on `<target-table>` violated
2023-05-29 23:31:01 +03:00
`<source-table>` does not exist
2023-05-12 00:30:15 +03:00
`GRANT` permission on `<source-table>` violated
`<new-table>` already exists
2023-05-29 23:31:01 +03:00
referential integrity violation on the updated `<target-table>`
2023-05-12 00:30:15 +03:00
unique key violation
-- for updateable `<target-table>` unique key violation is a violation of the primary index or any other unique index defined on the table
2023-05-29 23:31:01 +03:00
-- for producing new base `<table>` output, `<target-table>` primary index determines unique key violations
-- for producing `PASS-THRU` output, columns referenced in `<merge-predicate>` determine unique key violations for row sub-types that include all of the referenced columns
-- for producing `PASS-THRU` output when `<merge-predicate>` is not present, or the produced row sub-type does not include all of the referenced columns, the entire row by value determines unique key violations