objective-c - 如果列的新值为空,则插入新行而不覆盖列
问题描述
假设我有一个MyTableName
包含三列的表:COLUMN_NAME_A
, COLUMN_NAME_B
, COLUMN_NAME_C
(为了简化,只有三列,实际上我可能有几十列)。在我当前的实现中,当我插入新行时,所有列都将被覆盖。如何仅覆盖新值不为空的列。一种方法是检查新值,如果它为 NULL,则从表中读取值并重写它。有更简单和/通用的方法吗?
- (void)insertEntries:(<id<PTDBGeneralInfoTableEntry>>)entry inDatabase:(FMDatabase *)db {
[db beginTransaction];
[self createTableInDatabase:db];
NSString *insertSQL = [NSString stringWithFormat:@"INSERT OR REPLACE INTO MyTableName"
"(%@, %@, %@)"
" VALUES(?, ?, ?)",
COLUMN_NAME_A,
COLUMN_NAME_B,
COLUMN_NAME_C];
NSArray* values = @[entry.valueA ? entry.valueA : [NSNull null],
entry.valueB ? entry.valueB : [NSNull null],
entry.ValueC ? entry.ValueC : [NSNull null]];
BOOL res = [db executeUpdate:insertSQL withArgumentsInArray:values];
[db commit];
}
- (void)createTableInDatabase:(FMDatabase *)db {
NSString* createTableSQL =
[NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ ("
"%@ TEXT NOT NULL PRIMARY KEY,"
"%@ INTEGER,"
"%@ REAL"
")",
COLUMN_NAME_A,
COLUMN_NAME_B
COLUMN_NAME_C
];
[db executeUpdate:createTableSQL];
}
解决方案
我认为你有两个选择。第一个是丑陋的,可能更慢,但据我所知是标准 SQL 并得到广泛支持。第二个不是标准的,但自版本 3.24.0 起受 SQLite 支持。
嵌入式选择
基于这个答案,你可以做类似的事情
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'))
);
这相当简单,但也有点难看,而且可能很慢。您拥有的列越多,您需要执行的嵌入选择就越多(实际上,您只需要它们用于具有潜在空值的列,但仍然如此),并且您拥有的行越多,选择所需的时间就越多。
上插
但是,如果您使用的是 SQLite 3.24.0 或更高版本,则可以使用所谓的upsert 语法
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_ 指的是要插入的新值(在我们解决冲突之前,它是“排除的”)。
推荐阅读
- python - 可扩展元素通过单击自行关闭
- sql - 为什么此更新不会失败?这是预期的行为吗?
- swift - 如何在 AVPlayer 中播放 240FPS 视频
- android - 定期刷新的列表视图?
- python - 生成具有字符 a、b 或 c 且长度等于 n 且最多 1 b 和 2 c 的所有字符串
- r - dplyr - 分组计数和除法
- html - 如何在悬停时显示父元素的兄弟?
- jestjs - 我可以对 axios-mock-adapter 使用 jest.fn() 相关检查吗?
- python - 如何简化python函数?
- javascript - 如何显示结果在每个页面上的显示方式?