为什么 sqlite 的删除总是成功,即使要删除的行不存在?

Why does sqlite's delete always succeed, even when the row to delete does not exist?

本文关键字:删除 不存在 成功 sqlite 为什么      更新时间:2023-10-16

创建表后,将数据插入其中,然后删除不存在的行,即使该行不存在,操作也会成功。当我删除实际存在的行时,它也成功了,并且该行实际上被删除了。为什么当我尝试删除不存在的行时没有发生错误?

我在 eclipse 上使用 sqlite3 和 c++。我一直在使用网络上找到的一些代码,以及我自己的代码。其他操作,如选择和插入工作正常。当行存在时,甚至当行不存在时,DELETE 也有效。

创建表

sql = "CREATE TABLE COMPANY("  
"ID INT PRIMARY KEY     NOT NULL," 
"NAME           TEXT    NOT NULL," 
"AGE            INT     NOT NULL," 
"ADDRESS        CHAR(50)," 
"SALARY         REAL );";

插入数据

sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "    
"VALUES (1, 'Paul', 32, 'California', 20000.00 ); " 
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  
"VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); "     
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" 
"VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" 
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" 
"VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
删除

(这是删除应该失败的地方,因为没有 ID 30(

rc = sqlite3_open("test.db", &db);
if( rc ) {
    cout << "ERROR ----> " << zErrMsg << endl;
  return(0);
} else {
    fprintf(stderr, "Opened database successfullyn");
}
/* Create SQL statement */
sql = "DELETE FROM COMPANY WHERE ID = 30";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
if( rc != SQLITE_OK ) {
    cout << "ERROR DELETING" << endl;
    fprintf(stderr, "SQL error: %sn", zErrMsg);
    sqlite3_free(zErrMsg);
} else {
    fprintf(stdout, "Deletion operation done successfullyn");
}
sqlite3_close(db);
我希望显示消息"删除错误",

但始终显示"删除操作成功完成",即使删除的 ID 不存在也是如此。

为什么当我尝试删除不存在的行时没有发生错误?

数据库返回受影响的行数(在您的情况下已删除(,它们不会引发错误,除非查询有问题。

检查行是否已被删除的唯一保证方法是执行具有相同条件的 SELECT 语句。事务控制在这里是一个重要因素,即如果某些事情导致回滚会发生什么?您是显式提交事务,还是允许它们自动提交?您不应该只依赖返回代码。如果你也做了一个COUNT,那么你肯定会知道,至少在你的会话中:

SELECT COUNT(*) FROM COMPANY WHERE ID = 30

如果在DELETE之后,COUNT 0,则该行不再存在。

注意:如果您需要并发,这种方法将很有帮助,这将迫使您使用不同的数据库引擎(例如PostgreSQL(。

我想答案是"这是设计使然"。

如果您需要知道零(或更多(行是否受到最后一个 DELETE 语句(或 INSERT 或 UPDATE(的影响,那么您可以考虑使用:

int sqlite3_changes(sqlite3*);

这将允许您在未删除任何行时做出相应的反应。

请参阅 https://www.sqlite.org/c3ref/changes.html