2012-02-17 30 views
1

我有一個這樣的數組中刪除:插入如果DB不存在,如果不是在一個數組

$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大的數據集。

那麼有沒有一種有效的方法來做到這一點?

謝謝。

回答

1

如果是我我會遍歷$services收集IDS:

$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 KEYthis stackoverflow question可能會幫助您完成最後一部分。

+0

不幸的是,Oracle不支持ON DUPLICATE KEY。這是一個MySql語法 – winkbrace 2012-02-17 11:01:27

0

我的答案是,沒有一個真正有效的方法來做到這一點。 我曾經想過合併,但爲了高效,首先將它插入臨時表中,您仍然會更好。那麼你可能只需截斷table_service,然後再從$ service數組中填充它。 即使Kristoffer的anwser可以工作,它仍然可能比截斷插入更慢。

這是我的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; 
}