【问题标题】:Deleting DB records which are not in .csv file - efficiency?删除不在 .csv 文件中的数据库记录 - 效率?
【发布时间】:2012-06-06 09:08:38
【问题描述】:

我目前正在处理 .csv 导入,它可以导入议程项目(例如活动)并将它们放入 MySQL 数据库中。我已经掌握了它的要点,但是有一段很麻烦的代码,我似乎无法解决如何修复它或使其更高效/更好。

对我来说麻烦的代码部分是当一个事件从2012-06-012012-06-01tuesdaysunday 举行时,你想检查其中一些值是否是allready 在数据库中(因为用户可能会使用一些调整后的值再次导入 .csv 文件)。我当前的代码最终在数据库中实现了正确的值,但它的完成方式有点麻烦。如果文件再次被导入,所有来自星期天的值都会再次被删除,因为我的检查首先在星期二通过 foreach,它将检查数据库值是否与星期二生成的值匹配。检查完成并将值插入数据库后,我的 foreach 会检查星期天的所有值(星期二不会被删除,因为我保留了一个包含所有先前插入值的数组),然后再次插入它们。 所以基本上当我导入一个 .csv 文件时,它会删除然后插入相同的值,我的问题是如何防止这种情况发生?

另外,如果您发现有任何改进此代码的方法(因为我真的觉得一开始这样做效率不高),请说出来,非常感谢。

这是检查事件重复的代码,如果您需要任何说明或其他代码,请告诉我:

//REPEAT DAYS OF THE WEEK
if(!empty($repeatDayOfTheWeek) && $repeatDayOfTheWeek != '')
{
    $daysOfTheWeek = explode(',', $repeatDayOfTheWeek);

    foreach($daysOfTheWeek as $key => $dayOfTheWeek)
    {
        if(!is_numeric($dayOfTheWeek))
        {
            continue;
        }

        unset($agendaI->agendaItemValues['stopDate']);

        $beginDate = strtotime($tempStartDate);
        $endDate = strtotime($tempStopDate);

        $dayDates = array();
        $arrayDatesInDb = array();

        if(!isset($previousInserts))
        {
            $previousInserts = array();
        }

        if($beginDate != '' && $endDate != '')
        {
            while($beginDate <= $endDate)
            {
                if(date('N', $beginDate) == $dayOfTheWeek)
                {
                    $dayDates[] = date('Y-m-d', $beginDate);
                }

                $beginDate = strtotime("+1 day", $beginDate);
            }

        $datesInDb = $agendaI->getAgendaItemsByExternId($externId);

        if(empty($datesInDb))
        {
            foreach($dayDates as $dayDate)
            {
                dump("Empty DB - INSERT: ".$dayDate);
                $agendaI->setAgendaItemValue('startDate', $dayDate);
                $agendaI->saveAgendaItem();
                $previousInserts[] = $dayDate;
            }
        }
        else
        {
            dump('DB with records');
            foreach($datesInDb as $dateInDb)
            {
                if(!in_array($dateInDb->startDate, $dayDates) && !in_array($dateInDb->startDate, $previousInserts))
                {
                    dump("Not in Item-array, but in DB - DELETE: ".$dateInDb->startDate);
                    $agendaI->deleteAgendaItem($dateInDb->id);
                }
            }

        foreach($dayDates as $dayDate)
        {
            foreach($datesInDb as $dateInDb)
            {
                if($dayDate == $dateInDb->startDate)
                {
                    $arrayDatesInDb[] = $dateInDb->startDate;
                    dump("In array & in DB - UPDATE: ".$dateInDb->startDate);
                    $agendaI->setAgendaItemValue('id', $dateInDb->id);
                    $agendaI->saveAgendaItem();
                    $previousInserts[] = $dayDate;
                }
            }
        }

    unset($agendaI->agendaItemValues['id']);

    foreach($dayDates as $dayDate)
    {
        if(!in_array($dayDate, $arrayDatesInDb))
        {
            dump("Not in DB-array but in Item-array - INSERT: ".$dayDate);
            $agendaI->setAgendaItemValue('startDate', $dayDate);
            $agendaI->saveAgendaItem();
            $previousInserts[] = $dayDate;
        }
    }
}

以下字段位于 .csv 中:

"Datum" "Tijdstip" "Evenement" "Locatie" "Website" "Toelichting" "Duits" "engels" "startdatum" "stopdatum" "herhalen dag van de week" "externid" "categorie" "via"

换句话说
我需要检查数据库中的记录是否与 .csv 中的记录相同。如果 csv 没有数据库的记录,我需要从数据库中删除它(我当前的代码就是这样做的,只是效率不高)

【问题讨论】:

  • 我可以问一下投反对票的原因吗?
  • @eggyal 已添加到问题中
  • @ 反对者,您能否发表评论,以便我至少知道什么是“缺乏研究努力/不清楚/无用”?谢谢
  • 需要明确的是,如果 CSV 包含 same startdatumstopdatumherhalen dag van de week?
  • @eggyal 是的,但是还有其他值可能已经改变。但这不是我提出问题的原因,原因是 “所以基本上当我导入 .csv 文件时,它会删除然后插入相同的值,我的问题是如何防止这种情况发生?”

标签: php mysql oop csv


【解决方案1】:

您可以在startdatumstopdatumherhalen dag van de week 列中定义UNIQUE 索引,而不是在PHP 中实现检查;然后使用 REPLACELOAD DATA 命令将与这些字段匹配的任何现有记录替换为新记录:

ALTER TABLE events ADD UNIQUE INDEX (startdatum, stopdatum, dag);

LOAD DATA INFILE '/path/to/foo.csv'
  REPLACE
  INTO TABLE events;

【讨论】:

  • 是有用的,但这并不能解决我的删除问题? (或者我不明白)我需要检查数据库中的记录是否与 .csv 中的记录相同。如果 csv 没有数据库的记录,我需要从数据库中删除它
  • @Bono:哦。现在我明白了!为什么不先TRUNCATE TABLE events 再执行LOAD DATA
  • 谢谢,我会调查的 ;)
  • @Bono:需要明确的是,这将删除 events 中的所有条目,然后将 CSV 的内容加载到表中;因此该表最终仅包含最新 CSV 中的内容,没有其他内容。这就是你所追求的吗?
  • 不,这就是我现在正在做的事情。我只是想检查某些记录。不过谢谢;)也有可能使用多个 CSV,因此从事件中删除所有条目将无益:P
【解决方案2】:

我最终通过以下方式解决了这个问题,没有为每个 $daysoftheweek 使用 foreach 并使用 array_diff:

            //REPEAT DAYS OF THE WEEK
            if(!empty($repeatDayOfTheWeek) && $repeatDayOfTheWeek != '')
            {
                $daysOfTheWeek = explode(',', $repeatDayOfTheWeek);

                $agendaI->setAgendaItemValue('stopDate', '');

                $beginDate = strtotime($startDate);
                $endDate = strtotime($stopDate);
                $dayDates = array();
                $dbValues = array();
                $dbValues['datum'] = array();
                $latestDbValues = array();
                $toBeDeletedKeys = array();

                while($beginDate <= $endDate)
                {
                    if(in_array(date('N', $beginDate), $daysOfTheWeek))
                    {
                        $dayDates[] = date('Y-m-d', $beginDate);
                    }

                    $beginDate = strtotime("+1 day", $beginDate);
                }

                $evenementenInDb = $agendaI->getAgendaItemsByExternId($externId);

                if(!empty($evenementenInDb))
                {
                    foreach($evenementenInDb as $evenementInDb)
                    {
                        $dbValues['agendaid'][] = $evenementInDb->id;
                        $dbValues['datum'][] = $evenementInDb->startDate;
                    }
                }

                foreach($dayDates as $dayDate)
                {
                    $key = array_search($dayDate, $dbValues['datum']); 
                    if($key !== false && is_numeric($key))
                    {
                        //UPDATE
                        $agendaI->setAgendaItemValue('id', $dbValues['agendaid'][$key]);
                        $agendaI->setAgendaItemValue('startDate', $dayDate);
                        $agendaI->saveAgendaItem();
                        $latestDbValues[] = $dayDate;
                        dump('UPDATE');
                    }
                    else
                    {
                        //INSERT
                        unset($agendaI->agendaItemValues['id']);
                        $agendaI->setAgendaItemValue('startDate', $dayDate);
                        $agendaI->saveAgendaItem();
                        $latestDbValues[] = $dayDate;
                        dump('INSERT');
                    }
                }

                $toBeDeleted = array_diff($dbValues['datum'], $latestDbValues);
                foreach($toBeDeleted as $value)
                {
                    $toBeDeletedKeys[] = array_search($value, $dbValues['datum']);
                }

                foreach($toBeDeletedKeys as $toBeDeletedKey)
                {
                    //DELETE
                    $agendaI->deleteAgendaItem($dbValues['agendaid'][$toBeDeletedKey]);
                    dump('DELETE');
                }
            }
            else 
            { 
                //Normal, non repeating event
                //INSERT
                if(!empty($agendaItem) && is_numeric($agendaItem->id))
                {
                    $agendaI->setAgendaItemValue('id',$agendaItem->id);
                }

                $agendaId = $agendaI->saveAgendaItem();
            }

【讨论】:

    猜你喜欢
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 2013-05-05
    • 1970-01-01
    • 2014-02-13
    • 2014-01-04
    相关资源
    最近更新 更多