通过 CSV 导出/导入 mysql json 对象

我正在使用一对 PHP 脚本。一个脚本从 MYSQL 数据库读取数据并将其导出到 csv 文件,然后第二个脚本使用 csv 将导出的 csv 文件上传到另一个 MySQL 数据库实例。数据库表 A(导出)和 B(导入)的结构相同。


这些脚本适用于“普通”MySQL 表和列类型。但是,当我们将它们应用于在其中一个列(MySQL 列类型为“json”)中存储 JSON 对象的 MySQL 表时,导入失败。


导出数据的脚本按预期工作,生成一个 CSV 文件,其中 JSON 对象被双引号括起来……就像行中的其他值一样。

导出的 CSV 文件中的行如下所示(最后一项是复杂的 json 对象,为简单起见缩写):


"894","Somebody","Related","2020-02-20","{"name1":"value1","name2":"value2","name3":"value3"}","expired"

在导出数据的 PHP 脚本中,它本质上是这样的:


$rowStr =   "894","Somebody","Related","2020-02-20","{"name1":"value1","name2":"value2","name3":"value3"}","expired";

file_put_contents($filepath, trim($rowStr), FILE_APPEND);

导出没有问题。行按预期出现在 CSV 文件中(与上述格式相同)。


我将 csv 读入另一个数据库的代码如下所示:


    $allRows = array_map('str_getcsv',file($fp)); // read the exported csv file where $fp is the path to the file


    foreach($allRows as $i => $row) {

        //get the col_names from the 2nd database table (identical to the first) where $ac-> is the class that handles data queries

        $col_names = $ac->get_table_column_names('databasename',$tablename);


        $update_arr = array();

        foreach($col_names as $i => $cname) {


            $update_arr[$cname['COLUMN_NAME']] = $val;              

        }


        //and write the row to the 2nd db's table

        $ac->create_update_table($update_arr,$tablename,FALSE);

   }

而且,如果重要的话,这里是“get_table_column_names”和“create_update_table”函数中使用的查询:


get_table_column_names //使用PDO


SELECT COLUMN_NAME,COLUMN_DEFAULT,DATA_TYPE FROM information_schema.columns WHERE table_schema = :db AND table_name = :table

创建更新表


INSERT INTO 'tablename' (field1, field2, field3, field4,json_object_column) VALUES ("894","Somebody","Related","2020-02-20","{"name1":"value1","name2":"value2","name3":"value3"}")


发生的事情是 JSON 对象中的“,”被视为字段分隔符,并且 JSON 被分解为数组节点。除了编写脚本来检测以“{ 和 } 结尾的字段”之外,我如何将整个 json 字符串作为一个字段读取(因为它在数据库中)?或者,也许有更好的方法来输出字符串,以便可以将其作为一个项目读取?


慕尼黑5688855
浏览 165回答 2
2回答

Cats萌萌

如果不是仅仅使用像file_put_contents()你这样的东西写出数据,而是使用一些为 CSV 文件设计的方法,这将为你完成大部分工作......要写入数据使用fputcsv(),这会转义分隔符(在这种情况下,“变为”)...$row = ["894","Somebody","Related","2020-02-20",'{"name1":"value1","name2":"value2","name3":"value3"}',"expired"];$fh = fopen($filepath, "a");fputcsv($fh, $row);fclose($fh);这将写入文件894,Somebody,Related,2020-02-20,"{""name1"":""value1"",""name2"":""value2"",""name3"":""value3""}",expired然后从文件中读取,一次只读一行并使用fgetcsv()...$fh = fopen($filepath, "r");print_r(fgetcsv($fh));   // This in a loop to read all linesfclose($fh);这表明Array(    [0] => 894    [1] => Somebody    [2] => Related    [3] => 2020-02-20    [4] => {"name1":"value1","name2":"value2","name3":"value3"}    [5] => expired)

Smart猫小萌

解决此问题的一种方法是创建数组的新副本并操作新数组并将 json 添加为原始数组的切片部分。$allRows = array_map('str_getcsv',file($fp)); $new_arr = [];foreach($allRows[0] as $key=>$item) {    $json = false;    if (substr($item,0,1) == '{') {        $json_start = $key;        $json = true;    }    if (substr($item,-2,2) == '}"') {        $json_stop = $key;        $json = true;        //Slice json-part from original array (in your case 4,5,6)        $sl = array_slice($allRows[0], $json_start, ($json_stop-$json_start)+1);        //Add the sliced part into key where json started        $new_arr[$json_start] = implode('',$sl);             }    if ($json === false) $new_arr[] = $item;}然后你在$new_arr.
打开App,查看更多内容
随时随地看视频慕课网APP