使用pgsql进行csv“UTF8”字符编码

时间:2012-08-27 12:44:38

标签: php postgresql csv utf-8 character-encoding

我们的客户向我们发送了一个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);

1 个答案:

答案 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

更好的方法

无论如何,你采取的方法是不必要的缓慢和低效。你应该是:

  • 开立交易
  • 在数据库中创建一个与CSV文件结构相同的临时表。
  • 使用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,因此无法更详细地说明UPDATEINSERT语句。如果您提供了table1或甚至只是INSERTUPDATE的架构,我可以说更多。没有样本数据,我无法运行语句来检查它们,我不想编写一些虚拟数据,所以上面的内容是未经测试的。实际上,完成代码留作学习练习。我不会用完全书面的陈述更新这个答案,你可以解决这个问题。

相关问题