【发布时间】:2014-09-29 22:51:06
【问题描述】:
我编写了一个脚本,允许客户端上传 CSV 数据文件,然后将其输入数据库。该脚本首先将 CSV 文件上传到服务器,然后脚本的第二部分读取 CSV 文件,然后将该信息输入到数据库中。
但是,当 CSV 数据插入数据库时,我收到以下错误:
SQLSTATE[42000]:语法错误或访问冲突:1064 你有一个 SQL 语法错误;检查与您对应的手册 MariaDB 服务器版本,可在附近使用正确的语法 'UK,Managed,Company UK Glasgow,Glasgow,G1 G1 1AA,3723,Completed,Scheduled,2014-03' 第 1 行
这是 CSV 数据:
account_number,customer_reference,billing_customer,division,customer_site,town,postcode,job_number,job_status,job_type,completion_date,description,waste_type,ewc_code,container,quantity,total_uom,co2_saving,total_resource,total_co2_saving,recovery_rate,disposal_method,waste_hierarchy,customer_order_date,job_notes,customer_ref_po,uploaded,processed,deleted
1,633,Company UK,Managed,Company UK Glasgow,Glasgow,G1 G1 1AA,3723,Completed,Scheduled,2014-03-24,24/05/2014 - General Waste,General Waste to Energy,20 03 01,Wheelie Bin 1100 Litre,4,320,0.84,0,0.03,0,Transfer Station,Incinerator,2014-05-27,,0,2014-08-05,1,0
这是带有上传和 CSV 插入脚本的控制器: $fileUpload = $this->createForm(new FileuploadType());
$request = $this->getRequest();
if($request->getMethod() == 'POST') {
$fileUpload->bind($request);
$dir = '/var/www/cwwa/web/uploads/csv/';
if($fileUpload->isValid()) {
$file2 = $fileUpload['attachment']->getData();
$file2->move($dir, $file2->getClientOriginalName());
$fileName = $file2->getClientOriginalName();
$uploadedFile = basename($dir.''.$file2->getClientOriginalName());
$recordData = array();
$table = 'enviro_figures_upload';
if (($file = fopen($dir.$fileName, "r")) !== FALSE) {
$row = 0;
while (($data = fgetcsv($file, 1000, ",")) !== FALSE) {
if ($row == 0) {
$fieldNames = $data;
$row++;
} else {
$recordData[] = $data;
$row++;
}
}
}
$fields = implode(',', $fieldNames);
foreach ($recordData as $record) {
$values = implode(',',$record);
$sql = "INSERT INTO $table ($fields) VALUES ($values);";
}
$rsm = new ResultSetMapping($dm);
$insert = $dm->createNativeQuery($sql, $rsm);
$result = $insert->getResult();
}
}
我给数据加了引号,还是出现错误。
编辑
我改变了这一行:
$values = implode(',',$record);
到这里:
$values = '"'.implode(',',$record).'"';
这会将引号添加到要添加的值中,但这会导致值字符串的任一侧出现引号。见下文:
An exception occurred while executing 'INSERT INTO enviro_figures_upload (account_number,customer_reference,billing_customer,division,customer_site,town,postcode,job_number,job_status,job_type,completion_date,description,waste_type,ewc_code,container,quantity,total_uom,co2_saving,total_resource,total_co2_saving,recovery_rate,disposal_method,waste_hierarchy,customer_order_date,job_notes,customer_ref_po,uploaded,processed,deleted) VALUES (1,633,Company UK,Managed,Company UK Glasgow,Glasgow,G1 G1 1AA,3723,Completed,Scheduled,2014-03-24,24/05/2014 - General Waste,General Waste to Energy,20 03 01,Wheelie Bin 1100 Litre,4,320,0.84,0,0.03,0,Transfer Station,Incinerator,2014-05-27,,0,2014-08-05,1,0);':
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UK,Managed,Company UK Glasgow,Glasgow,G1 G1 1AA,3723,Completed,Scheduled,2014-03' at line 1
编辑 2
继 VMai 的评论后提出以下建议:
$values = '"' . implode('","',$record) . '"';
这解决了 SQLSTATE 问题。但是,它引发了一个新问题:
SQLSTATE[HY000]:一般错误
我检查了数据库并且查询确实插入了一行数据,无论 CSV 文件中有多少行。刷新页面然后将同一行数据插入到数据库中。
【问题讨论】:
-
仍然缺少开头和结尾的单引号:
$values = "'". implode(',',$record) . ".";应该这样做。但这不是一个可靠的解决方案。如果其中一个字段包含单引号或类似的东西怎么办? -
正如您所说,某些实际数据确实包含单引号。我想我可以反转它,做
'"'。我会试试这个。 -
假设 Doctrine 为 ORM,我建议使用准备好的语句,看看docs.doctrine-project.org/projects/doctrine-dbal/en/latest/…。有些值肯定也会有双引号......
-
我已根据您的第一条评论更新了我的答案。
-
我观察得不够多 :-( 你必须与你的引号保持一致并引用 csv 文件的每个字段:它应该是
$values = '"' . implode('","',$record) . '"';以使所有值正确引用双引号。希望您的值中没有像19" rack这样的值...
标签: mysql sql symfony csv mariadb