I am using DeltaLake API to update rows in a table using the code below
DeltaTable.forPath(sparkSession, cleanDataPath)
.as("target")
.merge(df.as("source"), "target.desk_mirror_name = source.desk_mirror_name AND target.price = source.price AND target.valuationdate = source.valuationdate AND target.valuationversion = source.valuationversion")
.whenMatched()
.updateAll()
.whenNotMatched()
.insertAll()
.execute();
This should match all the columns between source and target tables, except for column valuationtag
Before merge, the target table is like the following
+----------------+------+-------------+----------------+------------+
|desk_mirror_name| price|valuationdate|valuationversion|valuationtag|
+----------------+------+-------------+----------------+------------+
| Sample|499.97| 2021-06-10| 210611170317|210611170317|
| Sample|967.93| 2021-06-10| 210611170317|210611170317|
| Sample| 500.0| 2021-06-10| 210611170317|210611170317|
+----------------+------+-------------+----------------+------------+
The source table (that should update the target table) is as follows
+----------------+------+-------------+----------------+------------+
|desk_mirror_name| price|valuationdate|valuationversion|valuationtag|
+----------------+------+-------------+----------------+------------+
| Sample|499.97| 2021-06-10| 210611170317| OFFICIAL|
| Sample| 500.0| 2021-06-10| 210611170317| OFFICIAL|
| Sample|967.93| 2021-06-10| 210611170317| OFFICIAL|
+----------------+------+-------------+----------------+------------+
Only valuationtag is changed into OFFICIAL. Having this, the updated table is
+----------------+------+-------------+----------------+------------+
|desk_mirror_name| price|valuationdate|valuationversion|valuationtag|
+----------------+------+-------------+----------------+------------+
| Sample|499.97| 2021-06-10| 210611170317| OFFICIAL|
| Sample| 500.0| 2021-06-10| 210611170317| OFFICIAL|
| Sample|967.93| 2021-06-10| 210611170317| OFFICIAL|
+----------------+------+-------------+----------------+------------+
So far so good.
The problem starts when a column (in both tables) contains null values. Let's say that column desk_mirror_name is changed to nulls in the target table
+----------------+------+-------------+----------------+------------+
|desk_mirror_name| price|valuationdate|valuationversion|valuationtag|
+----------------+------+-------------+----------------+------------+
| null|499.97| 2021-06-10| 210611170317|210611170317|
| null|967.93| 2021-06-10| 210611170317|210611170317|
| null| 500.0| 2021-06-10| 210611170317|210611170317|
+----------------+------+-------------+----------------+------------+
With a source table having exactly the same data, except for valuationtag being changed into OFFICIAL, the updated table, strangely, have new lines inserted, instead of being merged. The result is the following
+----------------+------+-------------+----------------+------------+
|desk_mirror_name| price|valuationdate|valuationversion|valuationtag|
+----------------+------+-------------+----------------+------------+
| null|499.97| 2021-06-10| 210611170317|210611170317|
| null|967.93| 2021-06-10| 210611170317|210611170317|
| null| 500.0| 2021-06-10| 210611170317|210611170317|
| null|967.93| 2021-06-10| 210611170317| OFFICIAL|
| null| 500.0| 2021-06-10| 210611170317| OFFICIAL|
| null|499.97| 2021-06-10| 210611170317| OFFICIAL|
+----------------+------+-------------+----------------+------------+
It seems that DeltaLake did not correctly handle desk_mirror_name, which is having null values, both in the source and target tables.
How to deal with such a specific situation ?