如果列的新值为null,则插入新行而不覆盖列

时间:2018-10-31 09:51:11

标签: objective-c sqlite sql-update

说我有一个包含三列的表GSON<input id="name" name="name" class="form-control" required minlength="4" appForbiddenName="bob" [(ngModel)]="hero.name" #name="ngModel" > <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger"> <div *ngIf="name.errors.required"> Name is required. </div> <div *ngIf="name.errors.minlength"> Name must be at least 4 characters long. </div> <div *ngIf="name.errors.forbiddenName"> Name cannot be Bob. </div> </div> MyTableNameCOLUMN_NAME_A(为简化起见,只有三列,实际上我可能有数十列)。在我当前的实现中,当我插入新行时,所有列都将被覆盖。如何仅覆盖新值不为null的列。一种方法是检查新值,如果它为NULL,则从表中读取该值并将其重写。 有没有更简单和/或通用的方法?

COLUMN_NAME_B

1 个答案:

答案 0 :(得分:0)

我认为您有2个选择。第一个比较丑陋,而且速度可能较慢,但据我所知,它是标准SQL并得到广泛支持。第二个不是标准的,但是从3.24.0版本开始,SQLite支持它。

嵌入式选择

基于this answer,您可以执行类似的操作

INSERT OR REPLACE INTO MyTableName
VALUES (
    'example_id',
     COALESCE(100, (SELECT COLUMN_NAME_B from MyTableName WHERE COLUMN_NAME_A = 'example_id')),
     COALESCE(1.0, (SELECT COLUMN_NAME_C from MyTableName WHERE COLUMN_NAME_A = 'example_id'))
);

这很简单,但也很丑陋,而且可能很慢。您拥有的列越多,您需要执行的嵌入选择就越多(实际上,您只需要具有潜在空值的列就可以使用它们,但仍然如此),而行越多,选择所花费的时间就越多。

Upsert

但是,如果您使用的是SQLite 3.24.0或更高版本,则可以使用所谓的upsert syntax

INSERT INTO MyTableName
VALUES ('example_id', 100, 1.0)
ON CONFLICT(COLUMN_NAME_A) DO UPDATE SET
    COLUMN_NAME_B = COALESCE(EXCLUDED.COLUMN_NAME_B, COLUMN_NAME_B),
    COLUMN_NAME_C = COALESCE(EXCLUDED.COLUMN_NAME_C, COLUMN_NAME_C);

其中EXCLUDED.COLUMN_NAME_表示要插入的新值(在我们解决冲突之前,此值已被“排除”)。