0

クライアントから、Postgresql 8.3.9 データベースの特定のテーブルにインポートする必要があるデータの CSV ファイルが送られてきました。データベースは UTF-8 文字エンコーディングを使用します。つまり、当社の CMS では、CMS を介してフランス語でデータベースに入力されるフランス語などの複数の言語を使用できます。クライアントが画像をサーバーにアップロードし、フランス語で「alt」タグを入力する機能があります。ただし、一括更新が必要なため、特定のテーブルにフィードするための CSV が送信されました (フランス語のイメージ alt タグ用)。

CSV には、「é」などの特殊文字が含まれています。たとえば、「Bottes Adaptées Amora Cuir Faux-Croco Fauve Photo d'Ensemble」などです。

イメージ自体は 2 つの場所でホストされます。1 つは CDN、もう 1 つはローカル データベース バックアップとローカル サーバー (Web サーバー) ファイル バックアップです。PHP スクリプトを使用して CSV ファイルを読み取り、「alt」タグが 2 つの場所 (Web データベースと CDN) で更新されるように必要な処理を行っています。

しかし、(PHPを使って)CSVを読み込んでみると、思うように文字が「出てこない」。データは「Bottes Adapt�es Amora Cuir Faux-Croco Fauve Photo d'Ensemble」として提供されます。

これはデータベースとは何の関係もないと思いますが、CSV データを読み取る PHP ファイルと関係があります。読み取っているデータを印刷しても、上記の特殊文字が上記のように印刷されず、特殊文字が認識されていないかのように印刷されます。他の文字は正常に印刷されます。

これが私が使用しているコードです(データベースと対話するためにここでいくつかの特別なカスタム関数が使用されているわけではありませんが、それらは無視できます)。CSVファイルは画像名の{列1}とALTタグの{列2}で構成されています。

$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-8UTF-8変換せずに接続でデータを送信する場合、接続client_encodingUTF-8.

確認するには、SHOW client_encodingPHP から SQL ステートメントとして実行し、結果を出力します。SET client_encoding = 'UTF-8'CSV をインポートする前にコードに追加し、それが役立つかどうかを確認してください。もちろん、CSV ファイルが実際に UTF-8 でエンコードされていると仮定します。そうでない場合は、UTF-8 にトランスコードするか、どのエンコーディングであるかを調べる必要がありますSET client_encoding

The Absolute Minimum Every Software Developers Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)PostgreSQL manual on character set supportを読んでください。

より良いアプローチ

とにかく、あなたがとっているアプローチは不必要に遅く、非効率的です。あなたは:

  • 取引の開始
  • CSV ファイルと同じ構造の一時テーブルをデータベースに作成します。
  • CSV 形式を指定する適切なオプションを使用pg_copy_fromして、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 joinIS NULL

より高速なCTEベースのバージョンを作成することもできたでしょうが、使用している Pg のバージョンを教えてくれなかったため、サーバーが CTE をサポートしているかどうかわかりませんでした。

あなたが省略したため、 orステートメントUPDATEについてこれ以上具体的に説明することはできません。あなたがスキーマを提供した場合、またはあなたまたは私がもっと言うことができたかもしれません。サンプル データがないと、ステートメントを実行してチェックすることができませんでした。また、ダミー データを作成する気にもならなかったため、上記はテストされていません。そのまま、コードを完成させることは学習課題として残されています。この回答を完全に書き留めたステートメントで更新するつもりはありません。UPDATEINSERTtable1INSERTUPDATE

于 2012-08-28T00:41:53.920 に答える