MySQL使用CSV文件存储在Blob字段中并加载数据Infile

o0lyfsai  于 2023-10-13  发布在  Mysql
关注(0)|答案(1)|浏览(92)

我正在使用一个数据库,它有一系列存储在blob字段中的csv文件。
我想使用select with 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作为文件路径,但没有成功。
请告知。谢谢

wz3gfoph

wz3gfoph1#

AFAIK,没有办法使用LOAD DATA INFILE直接从存储在blob中的CSV文件加载数据。
引用MySQL文档:
LOAD DATA语句以非常高的速度将行from a text file读入表中。
假设一个表my_blobs如下:
| ID|二进制大对象数据|
| - -|- -|
| 1| "col head 1"、"col head 2"、"col head 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将文件读回目标表。这更加灵活,因为您可以根据my_blobs表中的元数据对LOAD DATA INFILE进行更改。
您可以使用这样的查询来编写dump/load脚本:

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文档):
一个给定的SELECT语句最多可以包含一个INTO子句,尽管如SELECT语法描述所示(参见Section 13.2.13, “SELECT Statement”),INTO可以出现在不同的位置:

  • 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开始支持语句末尾的INTO位置,这是首选位置。从MySQL 8.0.20起,锁定子句前的位置已弃用;希望在未来的MySQL版本中删除对它的支持。换句话说,INTOFROM之后但不在SELECT的末尾产生警告。
另一个来自docs的引用:
文件名必须以文字字符串形式给出。在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'

相关问题