2016-11-12 89 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); 
}