mysql 使用存储在 blob 字段中的 CSV 文件,并加载数据 infile

Mysql Using CSV Files Stored In Blob Field With Load Data Infile

提问人:dickey 提问时间:9/20/2023 最后编辑:Mark Rotteveeldickey 更新时间:9/29/2023 访问量:166

问:

我正在使用一个数据库,该数据库在 blob 字段中存储了一系列 csv 文件。

我想使用带有 where 子句的选择选择正确的文件 (.csv),然后通过拆分每个逗号分隔的列来为 .csv 中的每一行插入记录。

通常,如果文件位于磁盘上,我会使用:

LOAD DATA INFILE 'file-path'
INTO TABLE some-table
FIELDS TERMINATED BY ','
IGNORE 1 ROWS;

或者,如果从选择中插入记录,我会使用:

INSERT INTO target-table
SELECT * FROM source-table
WHERE condition;

我还尝试将包含文件的表上的选择结果作为变量传递给 LOAD DATA INFILE 作为文件路径,但没有成功。

请指教。谢谢。

mysql csv blob load-data-infile

评论

1赞 dickey 9/20/2023
感谢您的回复 user1191247。我将尝试这种方法并报告。
1赞 dickey 9/20/2023
这与突出显示的问题不是重复的问题。我之前读过这个问题。我的问题涉及选择一个 blob,然后解析其内容,然后将文件的每一行插入到表中(最好是在单个操作中)。另一个问题仅与使用“加载数据infile”插入 blob 数据有关。这两个问题都有一些共同的关键词,但显然不相关。过度热衷于重复对任何人有什么帮助?
1赞 dickey 9/21/2023
谢谢user1191247。是的,你的方法效果很好。我所做的唯一改进是使用适当的环境变量将转储文件写入临时目录,以便之后删除转储文件(仅此过程需要)。

答:

0赞 user1191247 9/29/2023 #1

AFAIK,无法直接从存储在 blob 中的 CSV 文件加载数据。LOAD DATA INFILE

引用MySQL文档中的一句话:

LOAD DATA 语句以非常高的速度将行读入表中。from a text file

假设一个表格,如下所示:my_blobs

编号 blob_data
1 “列头 1”,“列头 2”,“列头 3”“行 1 列 1”,“行 1 列 2”,“行 1 列 3”,“行 2 列 1”,“行 2 列 2”,“行 2 列 3”


......
2 ...
3 ...

一种简单的方法是将表中的所有 CSV 数据导出到单个文件中,然后导入它。仅当 blob 中的文件结构相同且没有(可能有限)编码差异时,这才有效。

SELECT TRIM(TRAILING '\n' FROM blob_data) FROM my_blobs
INTO OUTFILE '/path/to/file.csv'
FIELDS ESCAPED BY '';

LOAD DATA INFILE '/path/to/file.csv'
INTO TABLE `some-table`
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n';

如果 blob 中的数据具有标题行,则标题将多次导入,但可以在导入后将其删除。

一种更复杂(但灵活)的方法是使用 SELECT ...INTO DUMPFILE,然后使用 LOAD DATA INFILE 将文件读回目标表。这更灵活,因为您可以根据表中的元数据对LOAD DATA INFILEmy_blobs

您可以使用这样的查询来编写转储/加载脚本:

SELECT CONCAT(
    'SELECT blob_data FROM my_blobs WHERE id = ', id,' INTO DUMPFILE \'/path/to/csv_export_', id,'.csv\';\n',
    'LOAD DATA INFILE \'/path/to/csv_export_', id,'.csv\'\nINTO TABLE `some-table`\nFIELDS TERMINATED BY \',\' ENCLOSED BY \'"\'\nLINES TERMINATED BY \'\\n\'\nIGNORE 1 ROWS;\n\n'
) FROM my_blobs
INTO OUTFILE '/path/to/process_csv_files.sql'
FIELDS ESCAPED BY '' ENCLOSED BY '';

这将创建包含如下内容的文件:/path/to/process_csv_files.sql

SELECT blob_data FROM my_blobs WHERE id = 1 INTO DUMPFILE '/path/to/csv_export_1.csv';
LOAD DATA INFILE '/path/to/csv_export_1.csv'
INTO TABLE `some-table`
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;


SELECT blob_data FROM my_blobs WHERE id = 2 INTO DUMPFILE '/path/to/csv_export_2.csv';
LOAD DATA INFILE '/path/to/csv_export_2.csv'
INTO TABLE `some-table`
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;


SELECT blob_data FROM my_blobs WHERE id = 3 INTO DUMPFILE '/path/to/csv_export_3.csv';
LOAD DATA INFILE '/path/to/csv_export_3.csv'
INTO TABLE `some-table`
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;

注意(来自MySQL文档):

给定的语句最多可以包含一个子句,尽管如语法描述所示(参见第 13.2.13 节 “SELECT 语句”),可以出现在不同的位置:SELECTINTOSELECTINTO

  • 以前。例:FROM

    SELECT * INTO @myvar FROM t1;
    
  • 在尾随锁定子句之前。例:

    SELECT * FROM t1 INTO @myvar FOR UPDATE;
    
  • 在 .例:SELECT

    SELECT * FROM t1 FOR UPDATE INTO @myvar;
    

从 MySQL 8.0.20 开始支持语句末尾的位置,并且是首选位置。从 MySQL 8.0.20 开始,锁定子句之前的位置已弃用;预计在未来的MySQL版本中将删除对它的支持。换言之,在 之后而不是在末尾产生警告。INTOINTOFROMSELECT

文档中的另一句话:

文件名必须以文本字符串的形式提供。在 Windows 上,将路径名中的反斜杠指定为正斜杠或双反斜杠。

# Typical Windows path with secure_file_priv set
'C:\\ProgramData\\MySQL\\MySQL Server 8.0\\Uploads\\file.csv'
# or
'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/file.csv'