Reading https://sqlite.org/c3ref/vtab_nochange.html and https://sqlite.org/vtab.html#the_xupdate_method would suggest that you might need to query sqlite3_vtab_nochange() in your xColumn function and, if it returns true, refrain from setting a value, which will, in turn, force sqlite3_value_nochange() to return true for that column. Remember that the arguments to xUpdate are: - old rowid/primary key - new rowid/primary key - list of field values If you are already handling sqlite3_vtab_nochange() correctly, then the "not changed" NULL value seems to be getting lost between generating the xUpdate arguments (Instructions 19-26 in the second code listing) and actually calling xUpdate (Instructions 30-35), i.e. in the internal "work to do" table. BTW: Note that Instructions 19-20 attempt to call xRowid in the first listing, but are replaced by retrieving the primary key in the second listing.