0

我们的客户向我们发送了一个 CSV 数据文件,我需要将其导入到 Postgresql 8.3.9 数据库中的特定表中。数据库使用UTF-8字符编码,即我们的CMS允许多种语言,例如法语,通过CMS以法语输入数据库。一种特殊的工具是让客户端将图像上传到服务器,然后用法语为它们输入“alt”标签。但是,由于需要进行批量更新,我们已收到一个 CSV 文件以供输入特定表格 - 用于图像 alt 标签,使用法语。

CSV 有一些特殊字符,例如“é” - 例如“Bottes Adaptées Amora Cuir Faux-Croco Fauve Photo d'Ensemble”

图像本身托管在两个地方 - 一个是 CDN,一个是本地数据库备份和本地服务器(Web 服务器)文件备份。我正在使用 PHP 脚本来读取 CSV 文件并执行必要的操作,以便在两个地方更新“alt”标签 - 我们的 Web 数据库和 CDN。

但是,当我阅读 CSV(使用 PHP)时,字符并没有像预期的那样“出来”。该数据以“Bottes Adaptèes Amora Cuir Faux-Croco Fauve Photo d'Ensemble”的形式发布。

我认为这与数据库没有任何关系,但它与我的 PHP 文件读取 CSV 数据有关。即使我打印它正在读取的数据,上面的特殊字符也不会像上面那样打印,它的打印就像特殊字符没有被识别一样。其他字符打印正常。

这是我正在使用的代码(这里没有使用一些特殊的自定义函数来与数据库交互,但可以忽略它们)。CSV 文件由 {column 1}(图像名称)和 {column 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);
4

1 回答 1

1

您仍然省略了关键信息 - 在寻求帮助时UPDATE不要UPDATE从代码中删除语句 - 而且您对问题的描述非常混乱,但有一些暗示正在发生什么。

不匹配的编码

您的 PHP 连接很可能client_encoding设置为UTF-8. 如果您在UTF-8没有转换的情况下通过连接发送数据,则连接client_encoding必须是UTF-8.

为了确认,SHOW client_encoding从 PHP 作为 SQL 语句运行并打印结果。在导入 CSV 之前添加SET client_encoding = 'UTF-8'到您的代码中,看看是否有帮助。当然,假设 CSV 文件确实是 UTF-8 编码的。如果不是,您需要将其转码为 UTF-8 或找出它编码方式SET client_encoding

阅读每个软件开发人员绝对、绝对必须了解 Unicode 和字符集(没有任何借口!)PostgreSQL 字符集支持手册

更好的方法

无论如何,您采用的方法不必要地缓慢且效率低下。你应该:

  • 开启交易
  • 在数据库中创建一个与 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我无法更具体地了解UPDATEorINSERT语句。如果您为您或我提供了架构,table1甚至只是为您INSERTUPDATE我提供了更多信息。如果没有样本数据,我无法运行这些语句来检查它们,而且我不想编造一些虚拟数据,因此上述内容未经测试。事实上,完成代码是一个学习练习。我不会用完整的陈述来更新这个答案,你可以解决这个问题。

于 2012-08-28T00:41:53.920 回答