Sqlite3 - 如何从 csv 导入 NULL 值

问题描述 投票:0回答:3

我已将 mysql 表转储为 CSV。在此 CSV 文件中,NULL 值写为

\N

现在我想将此数据导入到 sqlite 数据库中,但我无法告诉 sqlite
\N
是空值。它将其视为字符串,并且该列值存储为“\N”而不是 NULL。

任何人都可以指导如何使用 sqlite 中的

.nullvalue
点命令。我无法将
\N
设置为空值。

sqlite> .show
nullvalue: ""
sqlite> .nullvalue \N
sqlite> .show
nullvalue: "N"
sqlite> .nullvalue '\N'
sqlite> .show
nullvalue: "\\N"
sqlite> .nullvalue "\N"
sqlite> .show
nullvalue: "N"
sqlite> .nullvalue \\N
sqlite> .show
nullvalue: "\\N"
sqlite> .nullvalue '\'N
Usage: .nullvalue STRING
sqlite> .nullvalue '\\'N
Usage: .nullvalue STRING
sqlite> .nullvalue \\N
sqlite> .show
nullvalue: "\\N"
sqlite>

这是每个

nullvalue

值之后的输出
sqlite> .import /tmp/mysqlDump.csv employee
sqlite> select count(*) from employee where updatedon='\N';
94143
sqlite> select count(*) from employee where updatedon is null;
0

如何告诉 sqlite 将

\N
视为 NULL 值? 我不能使用空字符串作为 NULL 值,因为我的数据包含空字符串。

mysql csv sqlite
3个回答
24
投票

CSV 文件仅包含文本值。无法从 CSV 文件导入 NULL 值。

要将

\N
值转换为 NULL,只需随后使用 UPDATE:

UPDATE employee SET updatedon = NULL WHERE updatedon = '\N';

3
投票

当 sqlite 配置为检查外键引用时,依赖于在导入后进行更新的方法是不可能的,因为导入将失败(外键约束将失败)并且不会有要更新的行。

为此,在导入后进行更新是不可接受的情况下,您必须修改合并中的 shell.c 文件(如下所示),并编译一个新的 sqlite(.exe) 二进制文件。

要做的更改是当字段为空时(使用

sqlite3_bind_null
)将字段的参数绑定为 NULL,而不是像目前所做的那样使用
sqlite3_bind_text
无条件地将其绑定为文本字段。

下面是对 sqlite 版本 v 3.33.0 2020-08-14 进行更改的示例(作为补丁差异)。

该示例在新的编译时选项

SQLITE_IMPORT_NULL_IF_EMPTY
背后进行了更改,因此要启用它,您需要在编译时定义它,如下所示:

cc -DSQLITE_IMPORT_NULL_IF_EMPTY <other options> shell.c sqlite3.c -o sqlite3

带有推荐选项(以及其他一些设置)的完整编译命令示例:

cc -Os -DSQLITE_IMPORT_NULL_IF_EMPTY -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_USE_ALLOCA -DSQLITE_OMIT_AUTOINIT -DSQLITE_DEFAULT_FOREIGN_KEYS=1 -DSQLITE_ENABLE_NULL_TRIM -DSQLITE_ENABLE_RBU -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DHAVE_USLEEP -DHAVE_READLINE shell.c sqlite3.c -lreadline -lncurses -o sqlite3

补丁文件内容:

--- sqlite-amalgamation-3330000/shell.c 2020-08-14 13:42:48.000000000 +0000
+++ shell.c     2020-10-07 13:23:39.000000000 +0000
@@ -17845,7 +17845,12 @@
         ** the remaining columns.
         */
         if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
+#ifdef SQLITE_IMPORT_NULL_IF_EMPTY
+        if (z==0 || z[0]=='\0') sqlite3_bind_null(pStmt, i+1);
+        else sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
+#else
         sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
+#endif
         if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
           utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
                           "filling the rest with NULL\n",

0
投票

更好一点的补丁:

+        if (p->nullValue[0] != '\0' && cli_strcmp(z, p->nullValue)==0) sqlite3_bind_null(pStmt, i+1);
+        else sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);

现在,当设置 .nullvalue 时,导入 CSV/TSV 文件时其值将替换为 NULL。

© www.soinside.com 2019 - 2024. All rights reserved.