【问题标题】:Export/import mysql json object via CSV通过 CSV 导出/导入 mysql json 对象
【发布时间】:2020-09-09 07:29:46
【问题描述】:

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

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

导出数据的脚本按预期工作,生成一个 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"}")

问题是,在导入时,行被转换成这样的数组:

array (
[0] = "894",
[1] = "Somebody",
[2] = "Related",
[3] = "2020-02-20",
[4] = "{name1":"value1",
[5] = "name2:"value2",  //should be part of node 4
[6] = "name3:"value3"}", //should be part of node 4
[7] = "expired"
);

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

【问题讨论】:

    标签: php mysql json csv object


    【解决方案1】:

    如果您不只是使用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 lines
    fclose($fh);
    

    显示

    Array
    (
        [0] => 894
        [1] => Somebody
        [2] => Related
        [3] => 2020-02-20
        [4] => {"name1":"value1","name2":"value2","name3":"value3"}
        [5] => expired
    )
    

    【讨论】:

    • 我尝试了这两种工具(fputcsvfgetcsv)的组合,但没有让它们工作。使用您明确的解决方案,它可以按预期工作!谢谢!我发现的一件小事是导出时fopen 的“a”设置至关重要。我曾尝试使用 'w' 进行 fopen 并且只在文件中写入一行。
    • 这是 fopen 中的模式,使用 w 将文件清空并允许您写入,a 打开用于写入并附加数据。看看php.net/manual/en/function.fopen.php的模式部分,还有更多选择。
    【解决方案2】:

    解决此问题的一种方法是创建数组的新副本并操作新数组 并将 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 中得到了你期望的数组。

    【讨论】:

      猜你喜欢
      • 2013-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2011-09-30
      • 2015-06-10
      相关资源
      最近更新 更多