1

I am new to PHP and am trying to update a deprecated code from mysql to PDO.

Considering that the variable $insert contains all values to bulk insert such as:

('82817cf5-52be-4ee4-953c-d3f4ed1459b0','1','EM3X001P.1a','04.03.10.42.00.02'),
('82817cf5-52be-4ee4-953c-d3f4ed1459b0','2','EM3X001P.2a','04.03.10.33.00.02'),

...etc 13k lines to insert

here is the deprecated code:

mysql_connect('localhost', 'root', '') or die(mysql_error()); 
mysql_select_db("IPXTools") or die(mysql_error());

if ($insert != '')
{
  $insert = "INSERT INTO IPXTools.MSSWireList (ID,Record,VlookupNode,HostWireLocation) VALUES ".$insert;
  $insert .= "ON DUPLICATE KEY UPDATE Record=VALUES(Record),VlookupNode=VALUES(VlookupNode),HostWireLocation=VALUES(HostWireLocation)";

  mysql_query($insert) or die(mysql_error());
  $insert = '';
}

here is the new code:

try 
{
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);    
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    //set the PDO error mode to exception

    // prepare sql and bind parameters
    $stmt = $conn->prepare("INSERT INTO IPXTools.MSSWireList (ID, Record, VlookupNode, HostWireLocation) 
    VALUES (:ID, :Record, :VlookupNode, :HostWireLocation)");
    $stmt->bindParam(':ID', $ID);
    $stmt->bindParam(':Record', $Record);
    $stmt->bindParam(':VlookupNode', $VlookupNode);
    $stmt->bindParam(':HostWireLocation', $HostWireLocation);    

    // insert a row
    // loop through all values inside the $insert variable??????? how?
    $stmt->execute();
}
catch(PDOException $e)
{
     echo "Error: " . $e->getMessage();
}
$conn = null;

During my research I found an excellent post: PDO Prepared Inserts multiple rows in single query

One method says I would have to change my $insert variable to include all the field names. And other method says I dont have to do that. I am looking at Chris M. suggestion:

The Accepted Answer by Herbert Balagtas works well when the $data array is small. With larger $data arrays the array_merge function becomes prohibitively slow. My test file to create the $data array has 28 cols and is about 80,000 lines. The final script took 41s to complete

but I didnt understand what he is doing and I am trying to adapt my code to his. The PHP sintax is new to me so I am strugling with handling the arrays, etc...

I guess the starting point would be the variable $insert which contains all the database values I need. Do I need to modify my $insert variable to include the field names? Or I could just use its content and extract the values (how?) and include the values in a loop statement? (that would probably execute my 13k rows one at at time)

Thank you

4
  • 1
    @JayBlanchard I don't see him using any mysql_* at all. Commented Jan 13, 2016 at 17:53
  • 1
    Your code looks fine, and you haven't actually posted any question. As far as the vague concerns raised in the linked question, that guy had issues because he did a dumb thing that: 1. Is unrelated to PDO. 2. You are not doing and don't need to do. Commented Jan 13, 2016 at 17:53
  • @JayBlanchard Yeah but that's the deprecated code he's trying to update to instead use PDO. Commented Jan 13, 2016 at 17:57
  • Ah, that wasn't clear in the first edit @PatrickGregorio Commented Jan 13, 2016 at 17:57

1 Answer 1

1

If you have 13k records to insert, it is good for performance to do not use prepared SQL statement. Just generate SQL query in format like this:

INSERT INTO IPXTools.MSSWireList 
(ID, Record, VlookupNode, HostWireLocation) 
VALUES 
('id1', 'r1', 'node1', 'location1'),
('id2', 'r2', 'node2', 'location2'),
...
('id13000', 'r13000', 'node13000', 'location13000');

What you may do for it - use maner of your legacy code. Your try block will looks loke this:

try 
{
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);    
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $conn->exec($insert);
}
Sign up to request clarification or add additional context in comments.

4 Comments

thanks man. That is exactly what I needed. Just to execute the command I had before in PDO. I thought I had to do all the binding. The only problem is that I am getting the error below which I am researching now: Warning: PDO::exec(): MySQL server has gone away in C:\xampp\htdocs\angular\IPXTool\version001\php\IPXTool_Admin_MSS_Ingest.php on line 162 Warning: PDO::exec(): Error reading result set's header in C:\xampp\htdocs\angular\IPXTool\version001\php\IPXTool_Admin_MSS_Ingest.php on line 162 Error: SQLSTATE[HY000]: General error: 2006 MySQL server has gone awayStatus::Ingested WireList.
just changed the max_allowed_packet inside my.ini in MySQL and restarted the service. Thanks you!
@mnv: I see that a separate prepared statement and execute for each data row is bad for performance, but what about using one prepared statement for all the data rows, as suggested here: stackoverflow.com/a/15070222/2737565 After all, prepared statements have the huge benefit of preventing SQL injection...
@Alexander Jank you may try that way for 100k+ records and compare execution time with my approach. Difference will be 10+ times, because linking data in PDO is heavy process.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.