我有一个创建csv文件的进程,该文件包含一组我需要导入MySQL数据库表中的字段的值。此过程创建一个特定的文件名,用于标识该表中其他字段的值。例如,文件名T001U020C075.csv将按如下方式细分:
T001 = Test 001
U020 = User 020
C075 = Channel 075
该文件包含由逗号分隔的单行数据,用于特定通道上该用户的所有测试结果,它可能类似于: 12.555,15.275,18.333,2.000 ......(每个用户每个频道有数百甚至数千个结果)。
我要做的是直接从CSV文件导入,添加文件名中的字段信息,使其看起来像:
insert into results (test_no, user_id, channel_id, result) values (1, 20, 75, 12.555)
我已尝试使用"批量插入"但似乎想要导入每个ROW都是记录的所有字段。当然,我可以进入每个文件并将行转换为列并将文件名中的数据添加到结果前面的列中,但这将是一项非常耗时的任务,因为已创建并需要数百个文件进口。
我发现了几个"导入CSV"解决方案,但他们都假设所有数据都在文件中。显然,它不是......
生成这些文件的过程无法修改(是的,我问过)。即使它可以被修改,它也只能提供适当的格式,所需要的是对历史数据的分析。并且,新格式将占用更多空间。
我只能使用MATLAB或MySQL Workbench导入数据。
感谢任何帮助。 鲍勃
答案 0 :(得分:0)
将数据加载到表中的一种可能的SQL方法是运行如下语句:
LOAD DATA LOCAL INFILE '/dir/T001U020C075.csv'
INTO TABLE results
FIELDS TERMINATED BY '|'
LINES TERMINATED BY ','
( result )
SET test_no = '001'
, user_id = '020'
, channel_id = '075'
我们需要逗号作为行分隔符。我们可以指定一些我们保证不会成为字段分隔符的字符。因此,我们会LOAD DATA
看到一个"字段"在每一行"行"。
(如果文件末尾没有尾随逗号,在最后一个值之后,我们需要测试以确保我们获得最后一个值(最后一个"行" as我们告诉LOAD DATA查看该文件。)
我们可以使用用户定义的变量来代替文字,但是留下了解析文件名的部分。这在SQL中真的很难看,但是可以做到,假设文件格式一致......
-- parse filename components into user-defined variables
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(f.n,'T',-1),'U',1) AS t
, SUBSTRING_INDEX(SUBSTRING_INDEX(f.n,'U',-1),'C',1) AS u
, SUBSTRING_INDEX(f.n,'C',-1) AS c
, f.n AS n
FROM ( SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( i.filename ,'/',-1),'.csv',1) AS n
FROM ( SELECT '/tmp/T001U020C075.csv' AS filename ) i
) f
INTO @ls_u
, @ls_t
, @ls_c
, @ls_n
;
在我们进行测试时,我们可能希望看到解析的结果。
-- for debugging/testing
SELECT @ls_t
, @ls_u
, @ls_c
, @ls_n
;
然后是关于运行实际LOAD DATA
语句的部分。我们必须再次指定文件名。我们需要确保我们使用相同的文件名...
LOAD DATA LOCAL INFILE '/tmp/T001U020C075.csv'
INTO TABLE results
FIELDS TERMINATED BY '|'
LINES TERMINATED BY ','
( result )
SET test_no = @ls_t
, user_id = @ls_u
, channel_id = @ls_c
(客户端需要读取权限.csv文件)
不幸的是,我们无法在程序中包装它,因为正在运行LOAD DATA
存储的程序不允许声明。
有些人会正确地指出,作为一种解决方法,我们可以编译/构建用户定义的函数(UDF)来执行外部程序,并且过程可以调用它。就个人而言,我不会这样做。但考虑到这些限制因素,我们应该提及它。