我们的客户向我们发送了一个CSV数据文件,我需要将其导入到Postgresql 8.3.9数据库的特定表中。数据库使用UTF-8字符编码,即我们的CMS允许多种语言,如法语,通过法语CMS输入数据库。一个特殊的工具是客户端将图像上传到服务器,然后用法语输入“alt”标签。但是,由于需要进行批量更新,我们已经发送了一个CSV文件,以法语形式输入特定的表格 - 图片alt标签。
CSV有一些特殊字符,例如“é” - 例如 “BottesAdapätesAmoraCuir Faux-Croco Fauve Photo d'Ensemble”
图像本身托管在两个位置 - 一个是CDN,一个是本地数据库备份和本地服务器(Web服务器)文件备份。我正在使用PHP脚本来读取CSV文件并做必要的事情,以便在两个地方更新“alt”标签 - 我们的网络数据库和CDN。
但是,当我读取CSV(使用PHP)时,角色不会按预期“出来”。 该数据将作为“BottesAdcadt esAmoraCuir Faux-Croco Fauve Photo d'Ensemble”。
我认为这与数据库没有任何关系,但它与我读取CSV数据的PHP文件有关。即使我打印正在读取的数据,上面的特殊字符也不会如上所示打印,它会打印出来,好像特殊字符无法识别一样。其他字符打印正常。
这是我正在使用的代码(这里没有使用一些特殊的自定义函数来与数据库交互,但可以忽略它们)。 CSV文件由{列1}表示图像名称,{列2}表示ALT标记。
$handle = fopen($conn->getIncludePath() . "cronjobs/GIB_img_alt_tags_fr.csv", "r");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
//normally I run a query here to check if the data exists - "SELECT imageid, image_fileref FROM table1 WHERE image_fileref = '". $data[0]. "'");
if ($conn->Numrows($result)) { //if rows were found -
$row=$conn->fetchArray($result);
//printing the data from $row here
}
}
fclose($handle);
答案 0 :(得分:1)
您仍然遗漏了关键信息 - 在向UPDATE
寻求帮助时不要从代码中删除UPDATE
语句 - 并且您对问题的描述非常困惑,但有一些暗示发生了什么。
您的PHP连接很可能将client_encoding
设置为UTF-8
以外的其他内容。如果您在未经转换的情况下向连接发送UTF-8
数据,则连接的client_encoding
必须为UTF-8
。
要确认,请从PHP运行SHOW client_encoding
作为SQL语句并打印结果。在导入CSV之前,将SET client_encoding = 'UTF-8'
添加到您的代码中,看看是否有帮助。当然,假设CSV文件实际上是UTF-8编码的。如果不是,则需要将其转码为UTF-8,或者找出 的编码和SET client_encoding
。
阅读The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)和the PostgreSQL manual on character set support。
无论如何,你采取的方法是不必要的缓慢和低效。你应该是:
pg_copy_from
将CSV加载到临时表中,并使用适当的选项指定CSV格式。使用INSERT
然后UPDATE
将临时表的内容合并到目标表中,例如:
INSERT INTO table1 (image_fileref, ... other fields ...)
SELECT n.image_fileref, ... other fields ...
FROM the_temp_table n
WHERE NOT EXISTS (SELECT 1 from table1 o WHERE o.image_fileref = n.image_fileref);
UPDATE table1 o
SET .... data to update ....
FROM the_temp_table n
WHERE o.image_fileref = n.image_fileref;
提交交易
INSERT
可以更有效地编写为带有left outer join
过滤器的IS NULL
,以排除匹配的行。这取决于数据。试试吧。
我可能已经编写了一个更快的基于CTE的版本,但你没有说你使用的是什么版本的Pg,所以我不知道你的服务器是否支持CTE。
由于您遗漏了UPDATE
,因此无法更详细地说明UPDATE
或INSERT
语句。如果您提供了table1
或甚至只是INSERT
或UPDATE
的架构,我可以说更多。没有样本数据,我无法运行语句来检查它们,我不想编写一些虚拟数据,所以上面的内容是未经测试的。实际上,完成代码留作学习练习。我不会用完全书面的陈述更新这个答案,你可以解决这个问题。