如何将我的数据添加到临时文件中,以便我可以使用 php for SQL server 执行 BULK INSERT?

问题描述

我正在构建一个项目,我将从 API 接收到的数据(有关产品的信息)复制到我的数据库中。我可以从 API 收到多个公司的产品。每个公司可以拥有 1 到 2.100.000 种产品。对于每个产品,我都会收到一个包含 60 个不同信息值的数组。我只在我的数据库中存储了 17 个这些值。可以想象,2.1M * 17 是很多要插入的数据。

我刚刚弄清楚 BULK INSERT 并研究了几个小时。我只是不知道如何正确创建我需要进行批量插入的文件。我想出了 tmpfile,但我不知道如何以正确的方式将我的数据放入此文件中。

我正在尝试复制 this example(第 3 点,带有最终提交的批量插入)以测试我的数据的速度有多快,但它是在 Java 中的。现在我错过了这个“addBatch()”和“executeBatch()”部分。这是他的代码

conn.prepareStatement("TruncATE TABLE testloadtable").execute();
conn.prepareStatement("ALTER SESSION SET sql_TRACE=TRUE").execute();
 
PreparedStatement stmt = conn.prepareStatement("INSERT /* addBatch insert */ INTO testloadtable (id,text) VALUES (?,?)");
 
for (int i=0;i<10000;i++)
{
  stmt.setInt(1,i);
  stmt.setString(2,"test" + i);
  stmt.addBatch();
}
stmt.executeBatch();
conn.commit();
 
conn.prepareStatement("ALTER SESSION SET sql_TRACE=FALSE").execute();

现在我使用此代码插入我的数据。它有效,但我只想测试 BULK INSERT 的速度有多快。 PS:我知道我的代码容易受到 sql 注入的攻击……也许批量插入可以解决这个问题。

function insertList($getData,$postData,$tableName) {
    global $conn;

    // For shorter code.
    $numberOfTradeItems = count($getData->TradeItems);

    // Loop trough all items received from API.
    for ($i = 0; $i < $numberOfTradeItems; $i++) {

        // Set data to a workable string for $query. str_replace to make sure query can use special characters. Especially the single qoutes.
        $values[] = "('". str_replace("'","''",$getData->TradeItems[$i]->TradeItemId) ."','". str_replace("'",$getData->TradeItems[$i]->Description) ."',". ifNullHandler($getData->TradeItems[$i]->GrosspriceInPriceUnit,true) .",'". $getData->TradeItems[$i]->AllowanceGroup ."',". ifNullHandler($getData->TradeItems[$i]->QuantityOfUseUnits,". ifNullHandler($getData->TradeItems[$i]->DeliveryTime,'". $getData->TradeItems[$i]->supplierGLN ."','". $getData->TradeItems[$i]->GTIN ."',$getData->TradeItems[$i]->Productcode) ."','". $postData->Products[$i]->ProductClassID ."',$postData->Products[$i]->ProductClassDescription) ."',$postData->Products[$i]->ManufacturerName) ."','". $getData->TradeItems[$i]->Deeplink ."',". ifNullHandler($getData->TradeItems[$i]->NumberOfUnitsInPriceBasis,'". $getData->TradeItems[$i]->OrderUnitMeasureUnitCode ."',". ifNullHandler($getData->TradeItems[$i]->MinimumOrderQuantity,0
        )";
        
        // Because db can only insert 1000 rows at a time. (count starts at 1). OR: check if this is the last item of the loop/array. Makes sure I do not get all data rounded on 1000 but all data that I can get.
        if (count($values) === 1000 || $i === ($numberOfTradeItems - 1)) {
            
            // Implode to make sure values that exists in $values will be added.
            $prepare = $conn->prepare("INSERT INTO [mydb].[dbo].[". $tableName ."] VALUES " . implode(',',$values));
            $prepare->execute();
        
            // To make sure next time the data won't be the same as before.
            $values = null;
        }
    }
}

我使用 sql Server 2019。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)