0

I would like to change my insert query. But how can i call procedure while using pdo in php. I was inserted table rows one by one with for loop. I want to do this with procedure. So, how should i do the query ? My insert query is below:

$connect = new PDO("mysql:host=;dbname=;charset=utf8", "username", "password");

$query = "
INSERT INTO siparis 
(product_id, p_code, p_name, p_type, p_quantity, p_listprice, p_netprice, p_total, preorderno, yetkili) 
VALUES (:pid, :p_code, :p_name, :dekorA, :p_quantity, :p_listprice, :p_netprice, :p_total, :preorderno, :yetkili)
";

for($count = 0; $count<count($_POST['hidden_p_code']); $count++)
{
    $data = array(
        ':pid'  =>  $_POST['hidden_pid'][$count],
        ':p_code'   =>  $_POST['hidden_p_code'][$count],
        ':p_name'   =>  $_POST['hidden_p_name'][$count],
        ':dekorA'   =>  $_POST['hidden_dekorA'][$count],
        ':p_quantity'   =>  $_POST['hidden_p_quantity'][$count],
        ':p_listprice'  =>  $_POST['hidden_p_listprice'][$count],
        ':p_netprice'   =>  $_POST['hidden_p_netprice'][$count],
        ':p_total'  =>  $_POST['hidden_p_total'][$count],
        ':preorderno'   =>  $_POST['hidden_preorderno'][$count],
        ':yetkili'  =>  $_POST['hidden_yetkili'][$count]
    );
    $statement = $connect->prepare($query);
    $statement->execute($data);
}

Procedure

DELIMITER //
CREATE PROCEDURE NEWLIST(
    IN pid int(11),
    IN p_code varchar(100),
    IN p_name varchar(100), 
    IN dekorA varchar(100),
    IN p_quantity varchar(100),
    IN p_listprice varchar(100),
    IN p_netprice varchar(100),
    IN p_total varchar(100),
    IN preorderno int(11),
    IN yetkili varchar(10)
)
BEGIN
INSERT INTO siparis(product_id, p_code, p_name, p_type, p_quantity, p_listprice, p_netprice, p_total, preorderno, yetkili) VALUES( pid, p_code, p_name, dekorA, p_quantity, p_listprice, p_netprice, p_total, preorderno, yetkili);
    END //
    DELIMITER ;

UPDATE It works with your suggestions, Thanks @Professor Abronsius

    $query = "CALL NEWLIST(:pid, :p_code, :p_name, :dekorA, :p_quantity, :p_listprice, :p_netprice, :p_total, :preorderno, :yetkili)";

for($count = 0; $count<count($_POST['hidden_p_code']); $count++)
{
    $data = array(
        ':pid'  =>  $_POST['hidden_pid'][$count],
        ':p_code'   =>  $_POST['hidden_p_code'][$count],
        ':p_name'   =>  $_POST['hidden_p_name'][$count],
        ':dekorA'   =>  $_POST['hidden_dekorA'][$count],
        ':p_quantity'   =>  $_POST['hidden_p_quantity'][$count],
        ':p_listprice'  =>  $_POST['hidden_p_listprice'][$count],
        ':p_netprice'   =>  $_POST['hidden_p_netprice'][$count],
        ':p_total'  =>  $_POST['hidden_p_total'][$count],
        ':preorderno'   =>  $_POST['hidden_preorderno'][$count],
        ':yetkili'  =>  $_POST['hidden_yetkili'][$count]
    );
    $statement = $connect->prepare($query);
    $statement->execute($data);
}
muhtarkator
  • 25
  • 1
  • 10
  • Does this answer your question? [PDO pass array into stored procedure](https://stackoverflow.com/questions/30298131/pdo-pass-array-into-stored-procedure) – Luuk Aug 07 '22 at 15:54
  • I ve to pass array values to "insert procedure" – muhtarkator Aug 07 '22 at 16:05

2 Answers2

0

You could be a little creative and build the entire query dynamically by interrogating the database schema and determining the parameters used within the stored procedure and from that build the placeholder string and generate the correctly formatted data parcel used in the execute method. For instance:

Given some source data to emulate the $_POST data in the question.

$_POST=array(
    array(
        'hidden_pid'=>23,
        'hidden_p_code'=>'abc-34',
        'hidden_p_name'=>'geronimo',
        'hidden_dekorA'=>'blah',
        'hidden_p_quantity'=>43,
        'hidden_p_listprice'=>99,
        'hidden_p_netprice'=>120,
        'hidden_p_total'=>150,
        'hidden_preorderno'=>2,
        'hidden_yetkili'=>'tiger'
    ),
    array(
        'hidden_pid'=>65,
        'hidden_p_code'=>'def-72',
        'hidden_p_name'=>'flatfoot',
        'hidden_dekorA'=>'aarrrggghhh',
        'hidden_p_quantity'=>643,
        'hidden_p_listprice'=>69,
        'hidden_p_netprice'=>420,
        'hidden_p_total'=>150,
        'hidden_preorderno'=>8,
        'hidden_yetkili'=>'leopard'
    ),
    array(
        'hidden_pid'=>84,
        'hidden_p_code'=>'toto-x1',
        'hidden_p_name'=>'desperate dan',
        'hidden_dekorA'=>'zing',
        'hidden_p_quantity'=>98,
        'hidden_p_listprice'=>89,
        'hidden_p_netprice'=>92,
        'hidden_p_total'=>100,
        'hidden_preorderno'=>5000,
        'hidden_yetkili'=>'lynx'
    )
);

And the given table structure

mysql> describe siparis;
+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| product_id  | int(10) unsigned | NO   | MUL | 0       |       |
| p_code      | varchar(50)      | YES  | MUL | NULL    |       |
| p_name      | varchar(50)      | YES  |     | NULL    |       |
| p_type      | varchar(50)      | YES  |     | NULL    |       |
| p_quantity  | varchar(50)      | YES  |     | NULL    |       |
| p_listprice | varchar(50)      | YES  |     | NULL    |       |
| p_netprice  | varchar(50)      | YES  |     | NULL    |       |
| p_total     | varchar(50)      | YES  |     | NULL    |       |
| preorderno  | int(11)          | YES  |     | NULL    |       |
| yetkili     | varchar(10)      | YES  |     | NULL    |       |
+-------------+------------------+------+-----+---------+-------+

And a simple Stored Procedure

DELIMITER //
CREATE PROCEDURE `NEWLIST`(
    IN `pid` int(11),
    IN `p_code` varchar(100),
    IN `p_name` varchar(100),
    IN `dekorA` varchar(100),
    IN `p_quantity` varchar(100),
    IN `p_listprice` varchar(100),
    IN `p_netprice` varchar(100),
    IN `p_total` varchar(100),
    IN `preorderno` int(11),
    IN `yetkili` varchar(10)
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
    INSERT INTO siparis
        ( `product_id`, `p_code`, `p_name`, `p_type`, `p_quantity`, `p_listprice`, `p_netprice`, `p_total`, `preorderno`, `yetkili` )
    VALUES
        ( pid, p_code, p_name, dekorA, p_quantity, p_listprice, p_netprice, p_total, preorderno, yetkili);
END //
DELIMITER ;

Then, in PHP, to build the query dynamically you could do this:

$sp='NEWLIST';  // The name of the Stored Procedure

$sql=sprintf('SELECT group_concat( ":",`parameter_name` ) as `placeholders`
                    FROM `information_schema`.`parameters`
                WHERE `SPECIFIC_NAME`="%s" and `specific_schema`=database()', $sp );
/*
    The above would yield a concatenated string such as
    
    :pid,:p_code,:p_name,:dekorA,:p_quantity,:p_listprice,:p_netprice,:p_total,:preorderno,:yetkili
    
    which looks good as the placeholder argument that you would
    supply to the stored procedure.
*/

$res=$connect->query( $sql )->fetch( PDO::FETCH_OBJ );
$placeholders=$res->placeholders;

# create the basic sql string statement
$sql=sprintf( 'call `%s`( %s );', $sp, $placeholders );

# we need the keys to generate the payload data used in `execute`
$keys=explode( ',', $placeholders );

# create the PDO prepared statement
$stmt=$connect->prepare( $sql );

# process the POST data using foreach for simplicity
foreach( $_POST as $arr ){
    # combine the keys with the values and execute the query
    $data=array_combine( $keys, array_values( $arr ) );
    $stmt->execute( $data );
}

This successfully populates the db with 3 records.

mysql> select * from siparis;
+------------+---------+---------------+-------------+------------+-------------+------------+---------+------------+---------+
| product_id | p_code  | p_name        | p_type      | p_quantity | p_listprice | p_netprice | p_total | preorderno | yetkili |
+------------+---------+---------------+-------------+------------+-------------+------------+---------+------------+---------+
|         23 | abc-34  | geronimo      | blah        | 43         | 99          | 120        | 150     |          2 | tiger   |
|         65 | def-72  | flatfoot      | aarrrggghhh | 643        | 69          | 420        | 150     |          8 | leopard |
|         84 | toto-x1 | desperate dan | zing        | 98         | 89          | 92         | 100     |       5000 | lynx    |
+------------+---------+---------------+-------------+------------+-------------+------------+---------+------------+---------+
3 rows in set (0.00 sec)

edit In response to the update you posted there are a couple of issues that need addressing, hopefully covered in the following. The changes made have not been tested in any way by me so, as you know, there might be errors.

try{
    /* 
        create and prepare SQL that analyses the stored procedure
        outside of any loop. Use the info obtained therein to build the
        dynamic SQL query that calls the stored procedure.
        
        This shuld be done ONCE, outside the loop. Within the loop that
        processes the POST data you only need to create the payload for 
        the SQL and execute the statement.
        
        As you had written it there was a new `$res=$connect->query( $sql )->fetch( PDO::FETCH_OBJ );`
        and `$stmt=$connect->prepare( $sql );` within the loop.
        
        
    */
    
    $sp='NEWLIST';  // The name of the Stored Procedure
    
    $sql=sprintf('SELECT group_concat( ":",`parameter_name` ) as `placeholders`
                    FROM `information_schema`.`parameters` WHERE
                    `SPECIFIC_NAME`="NEWLIST" and
                    `specific_schema`=mydbname', $sp );
                    
    $res=$connect->query( $sql )->fetch( PDO::FETCH_OBJ );
    $placeholders=$res->placeholders;
    
    $sql=sprintf( 'call `%s`( %s );', $sp, $placeholders );     
    $keys=explode( ',', $placeholders );
    $stmt=$connect->prepare( $sql );
        
        
        
    for( $count = 0; $count < count( $_POST['hidden_p_code'] ); $count++ ) {
        $main_arr = array(
            ':pid'          =>  $_POST['hidden_pid'][$count],       
            ':p_code'       =>  $_POST['hidden_p_code'][$count],
            ':p_name'       =>  $_POST['hidden_p_name'][$count],
            ':dekorA'       =>  $_POST['hidden_dekorA'][$count],
            ':p_quantity'   =>  $_POST['hidden_p_quantity'][$count],
            ':p_listprice'  =>  $_POST['hidden_p_listprice'][$count],
            ':p_netprice'   =>  $_POST['hidden_p_netprice'][$count],
            ':p_total'      =>  $_POST['hidden_p_total'][$count],
            ':preorderno'   =>  $_POST['hidden_preorderno'][$count],
            ':yetkili'      =>  $_POST['hidden_yetkili'][$count]        
        );
        /*
            create the payload used in the SQL execute method and then commit to db.
        */
        $data=array_combine( $keys, array_values( $main_arr ) );
        $stmt->execute( $data );
    }
} catch( PDOException $e ){
    return "Insert failed: " . $e->getMessage();    
}
Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
  • I'm sorry for the late reply. It's not working on me. Am i doing something wrong ? – muhtarkator Aug 21 '22 at 00:33
  • You would have to post the code that you are now trying (perhaps a pastebin?) because I have no means of knowing what you may have done. The above however works as it is - tested. – Professor Abronsius Aug 21 '22 at 06:54
  • I found where to problem, we forgot to put quotes on mydbname It should be like this "mydbname" – muhtarkator Aug 22 '22 at 13:20
  • Thanks for huge help Professor <3 – muhtarkator Aug 22 '22 at 13:21
  • I cant insert over 83 rows and im not taking any error messages, also already increased max_allowed_packet(500MB) and used distinct inside group_concat still cant insert it over 83 rows. If im trying to insert with manually, i can insert it like INSERT INTO tablename(column1,column2) values (data1,data2), (data3,data4). Do you have any suggestion about it ? – muhtarkator Aug 23 '22 at 06:20
  • is it hitting a timeout? 83 rows does no sound very high but I have no means to debug for myself. Try running your script without executing the actual prepared statement and maybe have some echo commands in to see where it fails ( if it does without the prepared statement ) – Professor Abronsius Aug 23 '22 at 06:27
  • it is not gives any timeout, `pdo` is not gives any error messages – muhtarkator Aug 23 '22 at 07:34
  • what is your current code? How large is the POST request? How many rows do you expect to add? I have no means to test this the way that you are using it – Professor Abronsius Aug 23 '22 at 07:39
  • im sending value from ajax post method. `var form_data = $(this).serialize(); $.ajax({ url:"insert.php", method:"POST", data: form_data, success:function(data) { link.click();//call to another query (just 1 row) $('#user_data').find("tr:gt(0)").remove(); $('#action_alert').html('

    Orderlist saved.

    '); $('#action_alert').dialog('open'); }` im testing between 100-200 rows
    – muhtarkator Aug 23 '22 at 07:43
  • 10 columns / 200 rows – muhtarkator Aug 23 '22 at 07:45
  • if it help you this is how i am creating table `output = ''; output += ''+pid+' ';` ... – muhtarkator Aug 23 '22 at 08:16
  • I have just created a test - generating semi-random data values for the array to be processed and it gladly ran and inserted 250 records in approx 8s – Professor Abronsius Aug 23 '22 at 08:28
  • I have now inserted close to a thousand records - I think the bottleneck with your code is not what I gave as an answer but perhaps in the javascript or other elements I have never seen. – Professor Abronsius Aug 23 '22 at 08:34
  • Do you think about server issues ? Im using raspberry pi 4, 4 gb ram remote server, but also im tesing it in my localhost from xampp the problems are same as both – muhtarkator Aug 23 '22 at 15:31
  • Im tested java post method sending to my all rows to insert.php – muhtarkator Aug 23 '22 at 15:34
  • When im trying to insert with for/while loop like dynamically its added maximum 83 rows, if im doing manually insert into like above its added all of my rows – muhtarkator Aug 23 '22 at 15:36
  • I have never tested it with just mysqli query, shall i follow to do that way – muhtarkator Aug 23 '22 at 15:38
  • [This was my test file](https://pastebin.com/jsEdeJUv) - without db connection details – Professor Abronsius Aug 23 '22 at 15:43
  • It is working on me aswell, so this problem is not in server side, probably in my index.php. But how is possible, ajax post method sending no matter how many lines i add. and insert.php reading how many request i add – muhtarkator Aug 23 '22 at 16:50
  • Perhaps create a pastebin of your complete code - I don't know how your app works or how it is built – Professor Abronsius Aug 23 '22 at 17:08
  • `"Error, this is a private paste or is pending moderation. If this paste belongs to you, please login to Pastebin to view it."` – Professor Abronsius Aug 23 '22 at 21:30
  • im new on pastebin sorry, try again please ? – muhtarkator Aug 23 '22 at 21:58
  • OK - I have put this together so that I can view your page but do not understand where/how this relates to the problem defined in your question. I was able to add several items (using dummy data ) and submit the form ( ajax ) but cannot reproduce your issues, sorry. I did not add more than 5 products and am not sure what your real problem is. – Professor Abronsius Aug 24 '22 at 07:46
  • The problem is, i cant add more than 83 rows. If you have mouse macro you can do trick to insert alot of products, You can do above "Add Product" while semi-click that button use that trick, left click > tab > enter > keydown > enter > tab > 1 > tab > tab > enter if you put loop inside that macro its working over 100 times – muhtarkator Aug 24 '22 at 12:21
  • And send that form to mysql, its add max 83 rows. – muhtarkator Aug 24 '22 at 12:33
  • Did you test it with 100+ records ? – muhtarkator Aug 24 '22 at 16:16
  • I tested **my php code** and happily more than 100 records could be inserted. I **have not** tested your Javascript and I have no means by which to test it other than rig up my own test which, sadly, I have no intention of doing. Your question has evolved from the original so much that you could, legitimately, open a new question to focus on the failings of your javascript and what is happening / not happening. To do that I **strongly** suggest creating a basic implementation of your code with everthing but the absolute essentials needed to produce the problem along with details of the problem – Professor Abronsius Aug 24 '22 at 18:03
  • Thank you for helping me so much. I hoped you would continue to help when you asked me for all of my codes. Thanks anyway for everything – muhtarkator Aug 24 '22 at 18:58
  • I simply cannot see how I can legitimately offer help when I cannot reproduce the problems that you are experiencing. Perhaps taking time to develop a streamlined question that exhibits the same problem will lead you to a conclusion either by your own endeavours or when posed as a standalone question where others will feel able to participate ( though they are welcome to do so here of course ). Let me know when you post a new question - good luck in the meantime – Professor Abronsius Aug 24 '22 at 21:15
  • [question link](https://stackoverflow.com/questions/73506910/ajax-post-method-php-limited-insert-query) – muhtarkator Aug 26 '22 at 22:35
0

Im really sorry asking from here, because too long for comment. i have been using your solution in my for loop and put them all in try catch. Am i doing wrong in somewhere ?

    try{
        $sql=sprintf('SELECT group_concat( ":",`parameter_name` ) as `placeholders`
        FROM `information_schema`.`parameters` WHERE
        `SPECIFIC_NAME`="NEWLIST" and
        `specific_schema`=mydbname', $sp );
    for($count = 0; $count<count($_POST['hidden_p_code']); $count++) 
    {
        $main_arr = array(
            ':pid'  =>  $_POST['hidden_pid'][$count],       
            ':p_code'   =>  $_POST['hidden_p_code'][$count],
            ':p_name'   =>  $_POST['hidden_p_name'][$count],
            ':dekorA'   =>  $_POST['hidden_dekorA'][$count],
            ':p_quantity'   =>  $_POST['hidden_p_quantity'][$count],
            ':p_listprice'  =>  $_POST['hidden_p_listprice'][$count],
            ':p_netprice'   =>  $_POST['hidden_p_netprice'][$count],
            ':p_total'  =>  $_POST['hidden_p_total'][$count],
            ':preorderno'   =>  $_POST['hidden_preorderno'][$count],
            ':yetkili'  =>  $_POST['hidden_yetkili'][$count]        
        );
        $res=$connect->query( $sql )->fetch( PDO::FETCH_OBJ );
        $placeholders=$res->placeholders;
        $sql=sprintf( 'call `%s`( %s );', $sp, $placeholders );
        $keys=explode( ',', $placeholders );
        $stmt=$connect->prepare( $sql );
        foreach( $main_arr as $arr ){
            $data=array_combine( $keys, array_values( $arr ) );
            $stmt->execute( $data );
        }
    }
}
catch(\PDOException $e){
    return "Insert failed: " . $e->getMessage();    
}

My second problem and my main problem, i couldn't insert over 83 rows to mysql. Im not taking any error messages. Adding over 100 rows to div table then when i used submit button then just inserts 83 rows, rest of them it doesn't inserted. If my order is under 83 rows, i am not having any problems. It adds directly to mysql. According to my research on stackoverflow, people have suggested increasing the max_allow_packet.

I also tried increase max_allowed_packet value from default(1048576 bytes) to 500MB(524288000 bytes). It doesn't work.

muhtarkator
  • 25
  • 1
  • 10