Вставьте, если не существует в БД, и удалите, если не в массиве - PullRequest
1 голос
/ 17 февраля 2012

У меня есть такой массив:

$services = array(
               array("id" => "1", "desc" => "desc 1"), 
               array("id" => "2", "desc" => "desc 2" ),
               ......
            );

Я хочу вставить эти службы в TABLE_SERVICE.каждый сервис вставляется, если он не существует в TABLE_SERVICE, и удаляет его, если он существует в TABLE_SERVICE, но не в массиве $services.

Я мог бы просто удалить все записи в TABLE_SERVICE и затем вставитьвсе элементы $services, но это может быть проблемой с производительностью, потому что у меня часто есть большой набор данных как TABLE_SERVICE, так и $services.

Так есть ли эффективный способ сделать это?

Спасибо.

Ответы [ 2 ]

1 голос
/ 17 февраля 2012

Если бы это был я, я бы повторил $services сбор идентификаторов:

$ids = array();
foreach($services as $service)
{
    $ids[] = $service['id'];
}

Затем с помощью PHP join и выбора NOT IN

"DELETE FROM TABLE_SERVICE WHERE id NOT IN (" . join($ids,',') . ")"

После этого снова итерацию по массиву для вставки / обновления, используя ON DUPLICATE KEY

"INSERT INTO TABLE_SERVICE (id,desc) VALUES (?,?) ON DUPLICATE KEY UPDATE desc = ?"

Поскольку у oracle нет ON DUPLICATE KEY , этот вопрос о переполнении стека может помочь вам с этой последней частью.

0 голосов
/ 17 февраля 2012

Я бы ответил, что на самом деле не существует эффективного способа сделать это. Я думал о слиянии, но чтобы быть эффективным, вам все равно лучше сначала вставить его во временную таблицу. Тогда вы можете просто усечь table_service и затем заполнить его снова из массива $ service. Даже если ответ Кристоффера может сработать, он все равно может работать медленнее, чем усеченная вставка.

Это мой метод php для быстрой вставки большого количества записей: Преимущество этого состоит в том, что ваш оператор вставки будет анализироваться только один раз вместо каждой вставки, что значительно повысит скорость. Иногда примерно в 100 раз.

$connection = oci_connect(<YOUR CONNECTION>);
$sql = insert into table_service (id, var) values (:id, :var); // desc is a reserved word, cannot be a column name
$parsed = oci_parse($connection, $sql);
$binds = array(':id', ':var');
$sizes = array(6, 20);
$data = $services;
$errors = execute_multiple($binds, $sizes, $data);
if ($errors > 0)
    // log or show
else
    // feedback: full succes!

function execute_multiple($binds, $sizes, $data, $commit = true)
{
    $errorCount = 0;

    // first determine all binds once
    foreach ($binds as $i => $bind)
    {
        // ${trim($bind, ':')} example:  :some_id -> $some_id
        oci_bind_by_name($parsed, $bind, ${trim($bind, ':')}, $sizes[$i]);
    }

    // Then loop over all rows and give the variables the new value for that row
    // This is because the variables remain binded!
    for ($row=0; $row<count($data); $row++)
    {
        foreach ($binds as $i => $bind)
        {
            $value = array_key_exists($i, $data[$row]) ? substr($data[$row][$i], 0, $sizes[$i]) : null;
            ${trim($bind, ':')} = trim($value);
        }

        if (! @oci_execute($this->parsed, OCI_DEFAULT))  // don't auto commit
            $errorCount++;
    }

    if ($commit)
        oci_commit($connection);

    return $errorCount;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...