You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么PHP执行LOAD DATA INFILE导入CSV时库存字段值为0

问题描述

我寻找该问题的解决方案已有近1年时间,具体情况如下:

  • 我的数据库部署在Ubuntu Apache服务器上,当前存储约200万条数据。供应商会定期上传库存文件,服务器每小时通过cron任务删除原有库存表后,从供应商提供的文件重新导入数据,保证库存水平和价格的时效性不超过1小时。
  • 供应商通常提供CSV或TXT格式的数据,我通过Apache服务器上的PHP文件执行LOAD DATA INFILE命令完成导入,支撑网站用户的数据库访问需求。
  • 整体流程对绝大多数供应商都运行正常,我会为每个供应商根据其文件格式编写专属的导入命令。但有一家供应商的CSV文件看起来正常,却出现导入问题:
    • 通过PHP脚本自动执行导入时,描述、价格等所有字段都能正常导入,唯独库存数量字段始终显示0,和CSV中的实际数值不符;但完全相同的命令在PHPMyAdmin中执行时,库存数量可以正常导入,因此可以确认源文件没有损坏。
    • 我试过将CSV文件重命名为TXT来消除格式影响,问题依旧;也尝试过将Quantity字段类型从INT(4)依次修改为FLOAT(4,0)、TEXT、VARCHAR,均导入失败:字段为VARCHAR类型时库存数据为空,其他数据类型时均显示为0。
    • 我已经检查过CSV文件中库存数量字段的格式为通用格式,无特殊格式设置,其他30余家供应商的同类文件均无异常,无法定位源数据的问题点。

相关代码

PHPMyAdmin中可正常执行的MySQL命令

LOAD DATA INFILE '/var/www/html/datafiles/FTP/company/company.txt' INTO TABLE `supplier-data` FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES (`Man_Pt_Nr`, `Sup_Pt_Nr`, `Manufacturer`, `Description`, `Qty`, `Cost`, `Condition`) SET `Disti` = 'Company Name', `shipping` = '£10.00';

PHP中执行会出现库存字段导入为0的代码

mysql_query ("LOAD DATA INFILE '/var/www/html/datafiles/FTP/company/company.txt' INTO TABLE `supplier-data` FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES (`Man_Pt_Nr`, `Sup_Pt_Nr`, `Manufacturer`, `Description`, `Qty`, `Cost`, `Condition`) SET `Disti` = 'Company Name', `shipping` = '£10.00';" );

导入数据样例

Manufacturer part number,SKU,Manufacturer name,Product name,Quantity in stock,Price list 1,Product condition code
500208-562-2304528AS,"2304528AS","Hewlett Packard Enterprise","1GB DDR3 PC3-10600 1333Mhz DIMM 240pin Ecc (AS)","19","2.00","AS"
E5470-NL-SB198-R4,"2337083R4","Dell","LAT E5470 i5-6300U/8GB/128GB-SSD/14""HD/W10P CMAR WLAN/BT/Single Point/Cover protection sticker (R4)","2","183.00","R4"
LAT7480-NL-SB106-R4,"2337512R4","Dell","FlexIT Dell Latitude 7480 (Refurbished)  7th gen Intel® Core? i5  2.6 GHz  35.6 cm (14"";)  1920 x 1080 pixels  8 GB  256 GB","68","378.00","R4"
EURO-C13-STD-5/6FT-N2,"2215545N2","Universal","EURO 230V C13 Power Cable Black 5-6ft/1 50-1 80M (N2)","14686","2.00","N2"
解决方案

根因说明

  • 核心问题是PHP代码中SQL语句的双引号未做转义,PHP解析字符串时会将SQL内部的双引号识别为字符串结束符,导致SQL语句被截断,字段映射顺序错乱,库存字段实际读取到的是其他列的内容,因此显示为0或空。
  • 次要问题是未兼容供应商文件的Windows格式换行符(\r\n),phpMyAdmin执行时会自动兼容多种换行符,而PHP中硬编码的\n会导致行解析错位,进一步加剧字段映射错误。
  • 当前使用的mysql_*系列扩展已被官方废弃,存在底层字符处理兼容性缺陷,也可能引发该问题。

修复步骤

  1. 修复PHP字符串转义问题,优先改用单引号包裹SQL字符串,避免内部双引号的转义冲突,示例如下:
// 改用单引号包裹SQL字符串,消除转义冲突
mysql_query('LOAD DATA INFILE \'/var/www/html/datafiles/FTP/company/company.txt\' INTO TABLE `supplier-data` FIELDS TERMINATED BY \',\' ENCLOSED BY \'"\' ESCAPED BY \'"\' LINES TERMINATED BY \'\r\n\' IGNORE 1 LINES (`Man_Pt_Nr`, `Sup_Pt_Nr`, `Manufacturer`, `Description`, `Qty`, `Cost`, `Condition`) SET `Disti` = \'Company Name\', `shipping` = \'£10.00\';');
  1. 将换行符设置为\r\n兼容Windows格式的库存文件,避免行解析错位。
  2. 若仍有异常,可通过用户变量接收原始字段内容,清洗掉不可见字符后再赋值给库存字段,参考SQL如下:
LOAD DATA INFILE '/var/www/html/datafiles/FTP/company/company.txt' 
INTO TABLE `supplier-data` 
FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"' 
LINES TERMINATED BY '\r\n' 
IGNORE 1 LINES 
(`Man_Pt_Nr`, `Sup_Pt_Nr`, `Manufacturer`, `Description`, @raw_qty, `Cost`, `Condition`) 
SET 
  `Disti` = 'Company Name', 
  `shipping` = '£10.00',
  `Qty` = CAST(TRIM(@raw_qty) AS UNSIGNED);
  1. 长远建议替换废弃的mysql_*扩展为mysqli或PDO,消除底层兼容性隐患。

内容的提问来源于stack exchange,提问作者Tony M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 13:15:03