使用php将嵌套的JSON导入MySQL

时间:2017-03-31 02:58:37

标签: php mysql arrays json

我正在寻找一种简单的解决方法,将现有的嵌套JSON数据导入到几个MySQL表中。 JSON没有双向关系,因此我认为它们应该自动生成。

以下是数据样本:

[
    {
        "targetgroup": "Staff",
        "plan": "this field just exists and should be ignored in database",
        "budgetlevel": "Government",
        "spots": 5,
        "edutype": "Bachelor",
        "qualilevel": "Specialist",
        "speciality": "Mathematician",
        "qualification": "Finished",
        "faculty": "Applied mathematics",
        "institute": "this field is sometimes empty in input data",
        "eduform": "Full-time",
        "profiles": [
            "Jr. Arithmetic manager"
        ],
        "entrancetests": [
            {
                "subject": "math",
                "typeoftest": "GOV",
                "minscore": "37",
                "ratingtype": "out of 100"
            },
            {
                "subject": "language",
                "typeoftest": "GOV",
                "minscore": "27",
                "ratingtype": "out of 100"
            },
            {
                "subject": "physics",
                "typeoftest": "GOV",
                "minscore": "40",
                "ratingtype": "out of 100"
            }
        ]
    },
  {
        "targetgroup": "Educational workers",
        "plan": "fridge",
        "budgetlevel": "Legacy",
        "spots": 26,
        "edutype": "Bachelor",
        "qualilevel": "Master",
        "speciality": "Data analysis",
        "qualification": "Finished",
        "faculty": "Machine learning mathematics",
        "institute": "",
        "eduform": "Full-time",
        "profiles": [
            "Head counting manager"
        ],
        "entrancetests": [
            {
                "subject": "Discrete mathematics",
                "typeoftest": "GOV",
                "minscore": "32",
                "ratingtype": "Out of 100"
            },
            {
                "subject": "Algorythm theory",
                "typeoftest": "GOV",
                "minscore": "51",
                "ratingtype": "Out of 100"
            },
            {
                "subject": "Advanced exception catching",
                "typeoftest": "GOV",
                "minscore": "56",
                "ratingtype": "Out of 100"
            }
        ]
    }
]

数据库结构:

表格“dep:”

id(自动增量)| targetgroup | budgetlevel |斑点| edutype ...等,与JSON字段名称相同

表格“个人资料”

id(相对于相应的父块)|名称

表“参加考试”:

id(相对于相应的父块)|主题| typeoftest | minscore | RATINGTYPE

我对如何导入非嵌套JSON有一个大概的想法,但我很难搞清楚如何添加关系,如何在循环中定义父块?提前谢谢。

1 个答案:

答案 0 :(得分:2)

圣诞快乐,mkrl。我们不应该为任何人编写新代码,我们只是想修复现有的编码尝试。然而,今天我想通过做更多的了解pdo,你的问题恰好是受益者。以下是针对您的具体情况的功能完备的事务性pdo过程。我已在我的服务器上测试了3个与您的结构相匹配的MyISAM表。现在,你可能不会进入pdo;如果没有,我希望我的产品能够让你尝试新的东西,并对查询数据库的方式进行现代化改造。

$json='[
    {
        "targetgroup": "Staff",
        "plan": "this field just exists and should be ignored in database",
        "budgetlevel": "Government",
        "spots": 5,
        "edutype": "Bachelor",
        "qualilevel": "Specialist",
        "speciality": "Mathematician",
        "qualification": "Finished",
        "faculty": "Applied mathematics",
        "institute": "this field is sometimes empty in input data",
        "eduform": "Full-time",
        "profiles": [
            "Jr. Arithmetic manager"
        ],
        "entrancetests": [
            {
                "subject": "math",
                "typeoftest": "GOV",
                "minscore": "37",
                "ratingtype": "out of 100"
            },
            {
                "subject": "language",
                "typeoftest": "GOV",
                "minscore": "27",
                "ratingtype": "out of 100"
            },
            {
                "subject": "physics",
                "typeoftest": "GOV",
                "minscore": "40",
                "ratingtype": "out of 100"
            }
        ]
    },
  {
        "targetgroup": "Educational workers",
        "plan": "fridge",
        "budgetlevel": "Legacy",
        "spots": 26,
        "edutype": "Bachelor",
        "qualilevel": "Master",
        "speciality": "Data analysis",
        "qualification": "Finished",
        "faculty": "Machine learning mathematics",
        "institute": "",
        "eduform": "Full-time",
        "profiles": [
            "Head counting manager"
        ],
        "entrancetests": [
            {
                "subject": "Discrete mathematics",
                "typeoftest": "GOV",
                "minscore": "32",
                "ratingtype": "Out of 100"
            },
            {
                "subject": "Algorythm theory",
                "typeoftest": "GOV",
                "minscore": "51",
                "ratingtype": "Out of 100"
            },
            {
                "subject": "Advanced exception catching",
                "typeoftest": "GOV",
                "minscore": "56",
                "ratingtype": "Out of 100"
            }
        ]
    }
]';


$db=new PDO("mysql:host=yourhost;dbname=yourdbname;charset=utf8","username","password");

try{
    $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);  // this will deny subsequent queries from being executed if there is an error and permit exception handle at the bottom
    $db->beginTransaction();

    // dep
    $dep_cols=array("targetgroup","budgetlevel","spots",
        "edutype","qualilevel","speciality","qualification",
        "faculty","institute","eduform");  // declare columns
    $dep_keys=array_map(function($v){return ":$v";},$dep_cols);  // build :keys    
    $dep_cols=array_combine($dep_keys,$dep_cols);   // assign :keys
    var_export($dep_cols);
    $dep_query="INSERT INTO `dep` (`".implode('`,`',$dep_cols)."`)"; // list columns as csv
    $dep_query.=" VALUES (".implode(',',array_keys($dep_cols)).");";
    echo "<div>$dep_query</div>";
    $stmt_add_dep=$db->prepare($dep_query);

    // profile
    $profile_cols=array('name');
    $profile_query="INSERT INTO `profile` (`id`,`".implode('`,`',$profile_cols)."`)"; // list columns as csv
    $profile_query.=" VALUES (LAST_INSERT_ID(),".implode(',',array_fill(0,sizeof($profile_cols),"?")).");";
    echo "<div>$profile_query</div>";

    // entrancetests
    $entrance_cols=array('subject','typeoftest','minscore','ratingtype');  // declare columns
    $entrance_keys=array_map(function($v){return ":$v";},$entrance_cols);  // build :keys
    $entrance_cols=array_combine($entrance_keys,$entrance_cols);  // assign :keys    
    var_export($entrance_cols);
    $entrance_query="INSERT INTO `entrancetests` (`id`,`".implode('`,`',$entrance_cols)."`)"; // list columns as csv
    $entrance_query.=" VALUES (LAST_INSERT_ID(),".implode(',',array_keys($entrance_cols)).");";
    echo "<div>$entrance_query</div>";
    $stmt_add_entrance=$db->prepare($entrance_query);

    foreach(json_decode($json) as $d){
        foreach($dep_cols as $k=>$v){
            $stmt_add_dep->bindValue($k,(property_exists($d,$v)?$d->$v:""));
            echo "<div>$k => {$d->$v}</div>";
        }
        $stmt_add_dep->execute();
        echo "<div>Dep Affected Rows: ",$stmt_add_dep->rowCount(),"</div><br>";

        $stmt_add_profile=$db->prepare($profile_query);
        foreach($d->profiles as $k=>$v){
            $stmt_add_profile->bindValue($k+1,$v);
            echo "<div>",$k+1," => $v</div>";
        }
        $stmt_add_profile->execute();
        echo "<div>Profile Affected Rows: ",$stmt_add_profile->rowCount(),"</div><br>";

        foreach($d->entrancetests as $o){
            foreach($entrance_cols as $k=>$v){
                $stmt_add_entrance->bindValue($k,(property_exists($o,$v)?$o->$v:""));
                echo "<div>$k => {$o->$v}</div>";
            }
        }
        $stmt_add_entrance->execute();
        echo "<div>Entrance Affected Rows: ",$stmt_add_entrance->rowCount(),"</div><br>";
    }

    // $db->commit();  // Only use with InnoDB tables.  MyISAM is auto-commit

}
catch(PDOException $e){
    // $db->rollBack();  // Only works if InnoDB table.  If MyISAM table, it doesn't rollback.
    echo "Error message: {$e->getMessage()}. File: {$e->getFile()}. Line: {$e->getLine()}";
    // do not show these error messages to users when you go live
}

按原样,如果查询有错误,此脚本将停止执行后续查询。

我知道有很多SO用户具有pdo流程方面的专业知识。如果有人发现任何问题或有可以改进我的代码的建议,请遏制向我投降的冲动;而只是给我一个建设性的评论,具体解释什么是不对的/好的,可能还有如何解决它。记住,SO的目的是帮助人们,而不是通过让别人失望来提升自己。我总是愿意编辑我的答案,以便未来的SO读者可以访问最好的代码。