MySQL从CSV数据加载空值

xdyibdwo  于 2023-02-15  发布在  Mysql
关注(0)|答案(8)|浏览(247)

我有一个文件,可以包含从3到4列的数值,由逗号分隔。空字段的定义与例外,当他们在行尾:

1,2,3,4,5
1,2,3,,5
1,2,3

下表是在MySQL中创建的:

+-------+--------+------+-----+---------+-------+
| Field | Type   | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+-------+
| one   | int(1) | YES  |     | NULL    |       | 
| two   | int(1) | YES  |     | NULL    |       | 
| three | int(1) | YES  |     | NULL    |       | 
| four  | int(1) | YES  |     | NULL    |       | 
| five  | int(1) | YES  |     | NULL    |       | 
+-------+--------+------+-----+---------+-------+

我正在尝试使用MySQL LOAD命令加载数据:

LOAD DATA INFILE '/tmp/testdata.txt' INTO TABLE moo FIELDS 
TERMINATED BY "," LINES TERMINATED BY "\n";

生成的表格:

+------+------+-------+------+------+
| one  | two  | three | four | five |
+------+------+-------+------+------+
|    1 |    2 |     3 |    4 |    5 | 
|    1 |    2 |     3 |    0 |    5 | 
|    1 |    2 |     3 | NULL | NULL | 
+------+------+-------+------+------+

问题在于当原始数据中的字段为空且未定义时,MySQL出于某种原因不使用列默认值(NULL)而使用零。当字段全部缺失时,NULL的使用是正确的。
不幸的是,在这个阶段我必须能够区分NULL和0,所以任何帮助都将不胜感激。
谢谢S。
编辑
演出警告的输出:

+---------+------+--------------------------------------------------------+
| Level   | Code | Message                                                |
+---------+------+--------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: '' for column 'four' at row 2 | 
| Warning | 1261 | Row 3 doesn't contain data for all columns             | 
| Warning | 1261 | Row 3 doesn't contain data for all columns             | 
+---------+------+--------------------------------------------------------+
owfi6suc

owfi6suc1#

这就是你想要的,它将第四个字段读入一个局部变量,然后如果局部变量最终包含一个空字符串,则将实际字段值设置为NULL:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(one, two, three, @vfour, five)
SET four = NULLIF(@vfour,'')
;

如果它们都可能是空的,那么你可以把它们都读入变量,并使用多个SET语句,如下所示:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(@vone, @vtwo, @vthree, @vfour, @vfive)
SET
one = NULLIF(@vone,''),
two = NULLIF(@vtwo,''),
three = NULLIF(@vthree,''),
four = NULLIF(@vfour,'')
;
e37o9pze

e37o9pze2#

MySQL manual表示:
使用LOAD DATA INFILE读取数据时,空列或缺少的列将使用''更新。如果希望列中有NULL值,则应在数据文件中使用\N。在某些情况下也可以使用文字"NULL"。
因此,您需要将空格替换为\N,如下所示:

1,2,3,4,5
1,2,3,\N,5
1,2,3
dw1jzc5e

dw1jzc5e3#

行为因数据库配置而异。在严格模式下,这将引发错误或警告。以下查询可用于标识数据库配置。

mysql> show variables like 'sql_mode';
ux6nzvsh

ux6nzvsh4#

预处理您的输入CSV以将空白条目替换为\N。
尝试正则表达式:s/,,/,\n,/g和s/,$/,\N/g
祝你好运。

xqnpmsa8

xqnpmsa85#

显示变量

Show variables like "secure_file_priv";
注意:保持您的csv文件在上述命令给定的位置.

create table assessments (course_code varchar(5),batch_code varchar(7),id_assessment int, assessment_type varchar(10), date int , weight int);

注:此处,csv文件中的“date”列有一些空白值。

LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/assessments.csv' 
INTO TABLE assessments
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '' 
LINES TERMINATED BY '\n' 
IGNORE 1 ROWS 
(course_code,batch_code,id_assessment,assessment_type,@date,weight)
SET date = IF(@date = '', NULL, @date);
6l7fqoea

6l7fqoea6#

(变量1,@variable2,..)设置变量2 = null如果(@variable2,“”或"“)〉〉您可以将任何条件

flvlnr44

flvlnr447#

在UNix终端中使用以下sed命令转换输入文件,以包含空白列数据的\N
sed -i 's/,,/,\\N,/g' $file_name
然后使用LOAD DATA INFILE命令加载到mysql

x7yiwoj4

x7yiwoj48#

MySQL将空字段转换为空字符串'',因此插入数值字段时会出错,因为从字符串到INT的转换不是一件事。即使创建表中的INT字段为DEFAULT NULL。直接的解决方案是预处理csv并将\N(而不是\n)作为NULL字段插入。这可以通过以下命令快速完成:

sed -i 's/,,/,\\N,/g file.csv'
sed -i 's/,,/,\\N,/g file.csv'

这样做两次很重要,因为连续的空白字段将被跳过,因为空白字段的第二个分隔符也是下一个字段的第一个分隔符,并且在第一次替换后将被跳过。
换句话说,如果只使用一个命令,something,,,,SomethingElse将转换为something,\N,,\N,SomethingElse
也许有一个更聪明的方法用一个更高级的命令来做这件事,但这工作得很好。你可以循环通过一个目录中的所有csv,并为每个文件运行命令两次。(reference

相关问题