我不想使用REPLACE INTO
,因为它基本上是DELETE
和INSERT
,并且使用旧列中的数据很复杂。
INSERT OR IGNORE
有点像黑客,因为所有错误都被忽略了,所以这不是一个选项。
我读过使用以下内容的blog article:
UPDATE Table1 SET (...) WHERE Column1='SomeValue'
IF @@ROWCOUNT=0
INSERT INTO Table1 VALUES (...)
我非常喜欢这种方法,但我不知道如何在SQLite中使用IF-clause
实现此@@ROWCOUNT
,这就是我所得到的:
SELECT CASE (SELECT
CASE
WHEN EXISTS(SELECT 1 FROM t WHERE id=2)
THEN 1
ELSE 0
END)
WHEN 1
UPDATE t set a='pdf' WHERE id=2;
ELSE
INSERT INTO t (a) VALUES ('pdf');
END
SELECT CASE
似乎是在SQLite中使用CASE-clause
的唯一方法,因为其他一切都会引发语法错误。但是也无法在UPDATE
中使用INSERT
- 或SELECT CASE
- 语句,因此会引发错误。
我尝试了以下
UPDATE t set a='pdf' WHERE id=2;
CASE WHEN (changes()=0) THEN
INSERT INTO t (a) VALUES ('pdf');
END
但这不起作用,因为CASE-clause
会引发语法错误。
有人可以使用@@ROWCOUNT
为SQLite中的UPSERT提供示例吗?
答案 0 :(得分:11)
SQLite没有内置类似UPSERT的语句,不会删除旧记录。
您应该检查程序中的更改次数,并有条件地执行INSERT。
但是,如果你真的想在SQL中这样做,那就有可能;但您必须使用INSERT ... SELECT ...
表单,以便在需要时能够插入零记录:
BEGIN;
UPDATE t SET a = 'pdf' WHERE id = 2;
INSERT INTO t(id, a) SELECT 2, 'pdf' WHERE changes() = 0;
COMMIT;
答案 1 :(得分:2)
在这种情况下,您应该使用sqlite API并在应用程序中编写“IF logic”。
sqlite3_prepare16_v2(stmt1, "UPDATE t SET a=? WHERE id=?");
sqlite3_prepare16_v2(stmt2, "INSERT INTO t(id, a) VALUES(?, ?)");
for(...) // iterate by rows to be updated/inserted
{
//set parameter values for stmt1
sqlite3_step(stmt1);
if( !sqlite3_changes(dbh) )
{
//set parameter values for stmt2
sqlite3_step(stmt2);
}
}