尝试插入或失败时,是否有一种处理select语句错误的好方法?具体来说,我想将元素插入表中,但用于生成这些元素的select语句失败。我想拥有成功插入select语句的所有元素,但是整个语句失败了。我认为插入或失败会这样做,但事实并非如此。更具体地说,假设我们定义了一个新的SQLite函数“log”
#include <string>
#include <sqlite3ext.h>
#include <cmath>
SQLITE_EXTENSION_INIT1
extern "C" {
int sqlite3_log_init(
sqlite3 * db,
char ** err,
sqlite3_api_routines const * const api
);
}
// Compute the log of the input
void mylog(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
// Grab the number
auto num = sqlite3_value_double(argv[0]);
// If positive, take the log
if(num > 0.)
sqlite3_result_double(context, log(num));
// Otherwise, throw an error
else {
auto msg = std::string("Can't take the log of a nonpositive number");
sqlite3_result_error(context,msg.c_str(),msg.size());
}
}
// Initialize the functions
int sqlite3_log_init(
sqlite3 *db,
char **err,
sqlite3_api_routines const * const api
){
SQLITE_EXTENSION_INIT2(api)
// Register the log function
if( int ret = sqlite3_create_function(
db, "log", 1, SQLITE_ANY, 0, mylog, 0, 0)
) {
*err=sqlite3_mprintf("Error registering log: %s",
sqlite3_errmsg(db));
return ret;
}
// If we've made it this far, we should be ok
return SQLITE_OK;
}
可以使用
编译g++ -std=c++14 log.cpp -shared -o log.so -fPIC
基本上,上面的函数获取其元素的日志。例如,
sqlite> select log(1);
0.0
sqlite> select log(0);
Error: Can't take the log of a nonpositve number
现在,考虑以下SQL操作序列
sqlite> .load "./log.so"
sqlite> create table foo (num real);
sqlite> insert into foo values (2.), (1.), (0.);
sqlite> create table bar (num real);
sqlite> insert or fail into bar select log(num) from foo;
Error: Can't take the log of a nonpositve number
sqlite> select * from bar;
sqlite>
基本上,表格栏是空的,因为select语句在0上失败。我想要的是表格栏包含元素log(2。)和log(1。),但错误仍然是被抛出有没有办法让这种情况发生?
答案 0 :(得分:1)
SQLite的ON CONFLICT clause仅适用于UNIQUE,NOT NULL,CHECK和PRIMARY KEY约束,因此您将无法使用INSERT或IGNORE。
一旦用户定义的函数返回错误,就无法抑制它。
你可以说函数的结果是未定义的,让它返回NULL(然后你可以过滤掉它)。
或者,只获取那些具有有效值的行:
INSERT INTO bar SELECT log(num) FROM foo WHERE num > 0;