2016-11-12 38 views
0

我有一個PHP數組,來自數據庫。這個數組我想插入到不同的數據庫/表。兩個字段(WEBINV_ID,HOSTNAME)是唯一的。我會每天更新這些表格每個腳本。如果條目存在,他們必須跳過插入,並應使用更新。這工作得很好。但是,如果我在運行PHP for循環,只會插入或更新數組的第一個進入新表 我用合併到一個PHP ARRAY插入表和爲了循環

MERGE INTO TABLE ... 

了點。 這是我輸入數組:

[0] => Array 
    (
     [CI_ID] => 39778 
     [NODEALIAS] => rt-2 
     [NODE] => 10.1.2.3 
     [SERIALNUMBER] => 8374378584 
     [VENDORNAME] => Cisco 
     [STATUS] => active 
    ) 

[1] => Array 
    (
     [CI_ID] => 72909 
     [NODEALIAS] => rt-1 
     [NODE] => 10.1.1.3 
     [SERIALNUMBER] => 1276731237 
     [VENDORNAME] => Cisco 
     [STATUS] => active 
    )... 

這裏是我的循環,我嘗試插入或更新我的所有設備。

for ($i = 0; $i < count($router); $i++) { 

    $sql = "MERGE INTO DEVICES USING (SELECT " 
      . "'" . $router[$i]['CI_ID'] . "' AS WEBINV_ID," 
      . "'" . $router[$i]['NODEALIAS'] . "' AS DEVICE_NAME," 
      . "'" . $router[$i]['NODE'] . "' AS NODE," 
      . "'" . $router[$i]['SERIALNUMBER'] . "' AS SERIALNUMBER," 
      . "'" . $router[$i]['VENDORNAME'] . "' AS VENDORNAME," 
      . "'" . $router[$i]['STATUS'] . "' AS STATUS," 
      . "CURRENT_TIMESTAMP AS DEVICE_INSERT FROM DUAL 
    ) S ON ('" . $router[$i]['CI_ID'] . "' = S.WEBINV_ID 
     OR '" . $router[$i]['NODEALIAS'] . "' = S.DEVICE_NAME) 
    WHEN MATCHED THEN UPDATE SET STATUS = '" . $router[$i]['STATUS'] . "', DEVICE_UPDATE = CURRENT_TIMESTAMP 
    WHEN NOT MATCHED THEN INSERT(WEBINV_ID,DEVICE_NAME,NODE,SERIALNUMBER,VENDORNAME,STATUS,DEVICE_INSERT) 
    VALUES ('" . $router[$i]['CI_ID'] . "'," 
      . "'" . $router[$i]['NODEALIAS'] . "'," 
      . "'" . $router[$i]['NODE'] . "'," 
      . "'" . $router[$i]['SERIALNUMBER'] . "'," 
      . "'" . $router[$i]['VENDORNAME'] . "'," 
      . "'" . $router[$i]['STATUS'] . "'," 
      . "CURRENT_TIMESTAMP)"; 

    $stid = oci_parse($gnedb, $sql); 
    oci_execute($stid); // executes and commits 
} 

我試過用「oci_bind_by_name」相同的代碼,但結果卻是一樣的,只是從陣列中使用的第一個條目。任何想法?

+1

一條記錄被合併的事實表明SQL語句是正確的。添加一個echo $ sql;聲明在oci_execute語句之前。數據中可能存在導致問題的內容。另一種方法 - 通過在oci_execute之後放置必要的oci錯誤語句來實際執行語句。 – jeff

+1

你確定該數組包含你認爲它包含的內容嗎? – Mihai

回答

0

如果您使用oci_bind_by_name我明白您使用Oracle數據庫。

也許你應該做這樣的事情:

$insert_query = "insert all "; 
foreach($router as $record) { 
    $fields = ""; 
    $values = ""; 
    foreach($record as $field => $value) { 
    $fields .= $field . ($field != 'STATUS' ? ',' : ""); // this is only if in the array the last field is STATUS - if it is not you might try to figure out last column diferently or remove last ',' differently 
    $values .= "'" . $value . "'" . ($field != 'STATUS' ? ',' : ""); // this is only if in the array the last field is STATUS - if it is not you might try to figure out last column diferently or remove last ',' differently 
    } 
    $insert_query .= " into devices (" . $fields . ") values (" . $values . ") "; 
} 

以上將創建一個查詢到$ insert_query,您只需將其發送到數據庫。 你需要弄清楚的唯一一件事就是應該引用哪些字段,哪些不能。我引用了所有這些,因爲Oracle應該能夠正確地施加值 - 但是您需要仔細檢查(我沒有Oracle可用來檢查它:))

我使用的SQL結構可以找到here

0

我發現了一個解決方案,我會添加我的工作代碼,只有這篇文章完成,我希望能幫助其他人。 這裏是代碼:

for ($i = 0; $i < count($router); $i++) { 
    $query = "MERGE INTO CORE_INTERFACES USING dual ON " 
     // The next row is the match criteria, like If "HOSTNAME" AND "IFINDEX" exist, Then Update else INSERT NEW HOSTNAMES! 
     . "(HOSTNAME = '" . $hostname . "' AND IFINDEX = '" . t trim($router_interface[0]) . "')" 
     . "WHEN MATCHED THEN UPDATE SET " 
     . "IFNAME = '" . trim($router_interface[1]) . "',IFTYPE = '" . trim(clean_iftype($router_interface[2])) . "',IFADMINSTATUS = '" . trim(clean_output($router_interface[3])) . "'," 
     . "LAST_UPDATE = CURRENT_TIMESTAMP " 
. "WHEN NOT MATCHED THEN INSERT (" 
     . "IF_ID,HOSTNAME,IFINDEX,IFNAME,IFTYPE,IFADMINSTATUS," 
     . "FIRST_SEEN " 
     . ") VALUES (" 
     . " core_interfaces_seq.nextval, " 
     . "'" . $hostname . "',"  //$HOSTNAME 
     . "'" . trim($router_interface[0]) . "',"  //ifIndex 
     . "'" . trim($router_interface[1]) . "',"  //ifName 
     . "'" . trim(clean_iftype($router_interface[2])) . "',"   //ifType 
     . "'" . trim(clean_output($router_interface[3])) . "',"   //ifAdminState 
     . " CURRENT_TIMESTAMP)"; 
    $stid = oci_parse($gnedb, $sql); 
}