Select table from Sql server and insert data to Mysql table - php

I have a running ms sql server and want some data copied to a mysql database.
i already can connect to them both so i made something like:
$pdo = new PDO('SQLSERVER', $user, $password);
$sql = "SELECT id, name FROM users";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$json_users = array();
while ($row = $stmt->fetchObject()){
$json_users[] = $row;
}
$pdo = new PDO('MYSQLDB', $user, $password);
foreach ($json_users as $key => $value){
$sql = "INSERT INTO users (id, name) VALUES (:id, :name)"
$stmt = $pdo->prepare($sql);
$stmt->bindParam('id', $value->id, PDO::PARAM_INT);
$stmt->bindParam('name', $value->name, PDO::PARAM_STR);
$stmt->execute();
}
this does work but takes a lot of time cause its a big table.
so my question is can i insert the complete results from sqlserver to mysql at once with only one insert query? without the foreach?
Update: the table contains 173398 rows and 10 columns

With prepared statements (especially for multi-insert) you want to have your prepared statement outside your loop. You only need to set the query up once, then supply your data in each subsequent call
$sql = "INSERT INTO users (id, name) VALUES (:id, :name)";
$stmt = $pdo->prepare($sql);
foreach($json_users as $key => $value){
$stmt->bindParam('id', $value->id, PDO::PARAM_INT);
$stmt->bindParam('name', $value->name, PDO::PARAM_STR);
$stmt->execute();
}

You can export this into CSV file first from MSSQL then import that file into MySQL.
$pdo = new PDO('SQLSERVER', $user, $password);
$sql = "SELECT id, name FROM users";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$fp = fopen('/tmp/mssql.export.csv', 'w');
while ($row = $stmt->fetch(PDO::FETCH_NUM)){
fputcsv($fp, array_values($row));
}
fclose($fp);
$pdo = new PDO('MYSQLDB', $user, $password, array(PDO::MYSQL_ATTR_LOCAL_INFILE => 1));
$sql = <<<eof
LOAD DATA LOCAL INFILE '/tmp/mssql.export.csv'
INTO TABLE user_copy
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
(id,name)
eof;
$pdo->exec($sql);
one drawback with the above, you need to have this configuration enabled in my.cnf ( MySQL configuration )
[server]
local-infile=1
Since MySQL cannot read files that are owned by others unless it it opened with --local-infile=1

I would suggest not bind values, but generate the query string:
$sql = "";
foreach ($json_users as $key => $value){
if ($sql=="") {
$sql = "INSERT INTO users (id, name) VALUES ";
$sql =." (".$value->id.',"'.$value->name.'")';
} else {
$sql .= ", (".$value->id.',"'.$value->name.'")';
}
}
$stmt = $pdo->prepare($sql);
$stmt->execute();
It is not best practice, but since you trust data source it could help.

Consider doing bulk inserts instead of one row at a time.
$sourcedb = new \PDO('SQLSERVER', $sourceUser, $sourcePassword);
$targetdb = new \PDO('MYSQLDB', $targetUser, $targetPassword);
$sourceCountSql = "SELECT count(*) count FROM users;";
/**
* for mssql server 2005+
*/
$sourceSelectSql = "
SELECT
id,
name
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY id) RowNum,
id,
name
FROM
users
) users
WHERE
RowNum >= %d
AND RowNum < %d
ORDER BY
RowNum
";
/**
* for mssql server 2012+
*/
$sourceSelectSql = "
SELECT
FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
SELECT
id,
name
FROM
users
ORDER BY
id
OFFSET %d ROWS
FETCH NEXT %d ROWS ONLY
";
$sourceCount = $sourcedb->query($sourceCountSql, \PDO::FETCH_COLUMN, 0);
$rowCount = 1000;
$count = 0;
$count2 = 0;
for($x = 0; $x < $sourceCount; $x += $rowCount) {
$sourceRecords = $sourcedb->query(sprintf($sourceSelectSql, $x, $rowCount), \PDO::FETCH_ASSOC);
$inserts = [];
foreach($sourceRecords as $row) {
$inserts[] = sprintf("(:id_%1$d, :name_%1$d)", $count++);
}
$stmt = $targetdb->prepare(sprintf("INSERT INTO users (id, name) VALUES %s;", implode(',', $inserts));
foreach($sourceRecords as $row) {
$stmt->bindParam(sprintf('id_%d', $count2), $row['id'], \PDO::PARAM_INT);
$stmt->bindParam(sprintf('name_%d', $count2), $row['name'], \PDO::PARAM_STR);
$count2++;
}
$targetdb->execute();
unset($inserts);
}

Related

Insert multiple rows into db table based on SELECT with qualifying rows from another table

I am trying to insert multiple values into the table row which are coming from the array.
I almost got the problem solved with this answer.
Best way to INSERT many values in mysqli?
please check the accepted answer. in this answer, he is adding the value in a single column but I want it in multiple columns.
how can I do this?
$array = array($u_id, $pid, $tradexx_price, $pvp, $product_title, $product_image);
$query = "INSERT INTO selection (c_id,p_id,tradexx_price,pvp,product_name,img) VALUES (?,?,?,?,?,?)";
$stmt = $con->prepare($query);
$stmt->bind_param("ssssss", $one);
$con->query("START TRANSACTION");
foreach ($array as $one) {
$stmt->execute();
}
$stmt->close();
$con->query("COMMIT");
but this code giving me an error.
Warning: mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables in
Any answers appreciated.
full script code
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
include '../includes/conn.php';
if (isset($_POST['insert_selection'])) {
$pid = implode(',', $_POST['id']);
$u_id = $_POST['u_id'];
foreach ((array)$pid as $p) {
$get_pro = "SELECT * FROM products WHERE id IN ($p)";
$run_pro = mysqli_query($con, $get_pro);
while ($row_pro = mysqli_fetch_array($run_pro)) {
$id = $row_pro['id'];
$product_title = $row_pro['product_title'];
$tradexx_price = $row_pro['product_price'];
$pvp = $row_pro['pvp'];
$product_image = $row_pro['product_image'];
$array = array($u_id, $id, $tradexx_price, $pvp, $product_title, $product_image);
$query = "INSERT INTO selection (c_id,p_id,tradexx_price,pvp,product_name,img) VALUES (?,?,?,?,?,?)";
$stmt = $con->prepare($query);
$stmt->bind_param("ssssss", $cur_c_id, $cur_id, $cur_tradexx_price, $cur_pvp, $cur_product_name, $cur_img);
$con->query("START TRANSACTION");
foreach ($u_id as $i => $cur_c_id) {
$cur_id = $id[$i];
$cur_tradexx_price = $tradexx_price[$i];
$cur_pvp = $pvp[$i];
$cur_product_name = $product_title[$i];
$cur_img = $product_image[$i];
$stmt->execute();
}
$stmt->close();
$con->query("COMMIT");
}
}
}
$pid is value from checkbox
You don't need a loop. You can use a SELECT query as the source of data for an INSERT.
error_reporting(E_ALL);
ini_set('display_errors', 1);
include '../includes/conn.php';
if (isset($_POST['insert_selection'])) {
$pid = implode(',', $_POST['id']);
$u_id = $_POST['u_id'];
$sql = "INSERT INTO selection (c_id,p_id,tradexx_price,pvp,product_name,img)
SELECT ?, id, product_price, pvp, product_title, product_image
FROM products
WHERE FIND_IN_SET(id, ?)";
$stmt = $con->prepare($sql);
$stmt->bind_param("i", $u_id, $pid);
$stmt->execute(); }
}

updating the data using implode in php

please help me out and sorry for my bad English,
I have fetch data , on basis of that data I want to update the rows,
Follows my code
I fetched data to connect API parameters
<?php
$stmt = $db->stmt_init();
/* publish store for icube*/
$stmt->prepare( "SELECT id,offer_id,name,net_provider,date,visible,apikey,networkid FROM " ."affilate_offer_findall_icube WHERE visible='1' ");
$stmt->execute();
mysqli_stmt_execute($stmt); // <--------- currently missing!!!
mysqli_stmt_store_result($stmt);
$rows = mysqli_stmt_num_rows($stmt);
$stmt->bind_result( $id, $offer_id, $name, $net_provider, $date, $visible,$apikey,$networkid);
$sql = array();
if($rows>0)
{
while($info = $stmt->fetch() ) {
$jsondataicube = file_get_contents('filename/json?NetworkId='.$networkid.'&Target=Affiliate_Offer&Method=getThumbnail&api_key='.$apikey.'&ids%5B%5D='.$offer_id.'');
$dataicube = json_decode($jsondataicube, true);
foreach($dataicube['response']['data'][0]['Thumbnail'] as $key=>$val)
{
$offer_id = $dataicube['response']['data'][0]['Thumbnail']["$key"]['offer_id'];
$display = $dataicube['response']['data'][0]['Thumbnail']["$key"]['display'];
$filename = $dataicube['response']['data'][0]['Thumbnail']["$key"]['filename'];
$url = $dataicube['response']['data'][0]['Thumbnail']["$key"]['url'];
$thumbnail = $dataicube['response']['data'][0]['Thumbnail']["$key"]['thumbnail'];
$_filename = mysqli_real_escape_string($db,$filename);
$_url = mysqli_real_escape_string($db,$url);
$_thumbnail = mysqli_real_escape_string($db,$thumbnail);
$sql[] = '("'.$offer_id.'","icube","'.$_thumbnail.'","'.$_url.'")';
}
}
As I store values which have to be inserted in 'sql'
now
$stmt->prepare( "SELECT offer_id FROM " ."affilate_offer_getthumbnail_icube ORDER BY 'offer_id' ASC");
$stmt->execute();
mysqli_stmt_execute($stmt); // <--------- currently missing!!!
mysqli_stmt_store_result($stmt);
$rows = mysqli_stmt_num_rows($stmt);
$stmt->bind_result($offer_id);
$sqlimplode = implode(',', $sql);
if($rows>0)
{
$query = "UPDATE affilate_offer_getthumbnail_icube WHERE offer_id='".$offer_id."' SET '".$sqlimplode."'";
$stmt->prepare( $query);
$execute = $stmt->execute();
}
else
{
$query= "INSERT INTO affilate_offer_getthumbnail_icube(offer_id, net_provider,logo2020,logo100) VALUES".$sqlimplode;
$stmt->prepare( $query);
$execute = $stmt->execute();
}`
`
Insert query working well,but how can I update all the data like insert query ?
My Answer is refering to a "set and forget"-strategy. I dont want to look for an existing row first - probably using PHP. I just want to create the right SQL-Command and send it.
There are several ways to update data which already had been entered (or are missing). First you should alter your table to set a problem-specific UNIQUE-Key. This is setting up a little more intelligence for your table to check on already inserted data by its own. The following change would mean there can be no second row with the same value twice in this UNIQUE-set column.
If that would occur, you would get some error or special behaviour.
Instead of using PHPMyAdmin you can use this command to set a column unique:
ALTER TABLE `TestTable` ADD UNIQUE(`tablecolumn`);
After setting up your table with this additional intelligence, you alter your Insert-Command a little bit:
Instead of Insert you can drop and overwrite your Datarow with
REPLACE:
$query= "REPLACE INTO affilate_offer_getthumbnail_icube
(offer_id, net_provider,logo2020,logo100) VALUES (".$sqlimplode.")";
See: Replace Into Query Syntax
Secondly you can do this with the "On Duplicate Key"-Commando.
https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
$query= "INSERT INTO affilate_offer_getthumbnail_icube
(offer_id, net_provider,logo2020,logo100)
VALUES (".$sqlimplode.")
ON DUPLICATE KEY UPDATE net_provider = ".$newnetprovider.",
logo2020 = ".$newlogo2020.",
logo100 = ".$newlogo100.";";
Note: I think you missed some ( and ) around your $sqlimplode. I always put them around your implode. Maybe you are missing ' ' around strings as well.
Syntax of UPDATE query is
UPDATE table SET field1 = value1, field2 = value2 ...
So, you cannot pass your imploded array $sql to UPDATE query. You have to generate another sql-string for UPDATE query.
This is clearly incorrect:
$query = "UPDATE affilate_offer_getthumbnail_icube
WHERE offer_id='".$offer_id."' SET '".$sqlimplode."'";
If the intention is to INSERT offer_id='".$offer_id."' and then UPDATE ... SET offer_id = '".$sqlimplode."'";
You have to use two separate queries, one for INSERT and then another one for UPDATE
An Example:
$query = "INSERT INTO affilate_offer_getthumbnail_icube
(col_name) VALUES('".$col_Value."')";
//(execute it first);
$query2 = "UPDATE affilate_offer_getthumbnail_icube SET
col_name= '".$col_Value."'" WHERE if_any_col = 'if_any_Value';
//(execute this next);
Try this:
$sqlimplode = implode(',', $sql);
if($rows>0)
{
/*$fields_values = explode(',',trim(array_shift($sql), "()"));
$combined_arr = array_combine(['offer_id','net_provider','logo2020','logo100'],$fields_values);
$sqlimplode = implode(', ', array_map(function ($v, $k) { return $k . '=' . $v; }, $combined_arr, array_keys($combined_arr))); */
$query = "INSERT INTO affilate_offer_getthumbnail_icube(offer_id, net_provider,logo2020,logo100) VALUES".$sqlimplode." ON duplicate key update net_provider = values(net_provider),logo2020 = values(logo2020),logo100 = values(logo100)";
$stmt->prepare( $query);
$execute = $stmt->execute();
}
else
{
$sqlimplode = implode(',', $sql);
$query= "INSERT INTO affilate_offer_getthumbnail_icube(offer_id, net_provider,logo2020,logo100) VALUES".$sqlimplode;
$stmt->prepare( $query);
$execute = $stmt->execute();
}

SQL insert into select issue

So i think i'm close to figuring this out but my query won't add the item from the "pending" table to the "items" table. can you guys help me out with this please. Also if i want it to delete after it gets added should i add the code below the INSERT INTO SELECT query? thanks
action.php:
$sql = "INSERT INTO items (photo,title,description, name) SELECT (photo,title,description, name) FROM pending";
$stmt = $conn->prepare($sql);
$stmt->execute();
Example for delete query after it takes the item from the "pending" into items:
$idToDelete = filter_var($_POST["recordToDelete"],FILTER_SANITIZE_NUMBER_INT);
//try deleting record using the record ID we received from POST
$sql = "DELETE FROM pending WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $idToDelete, PDO::PARAM_INT);
$stmt->execute();
I think you are leaving yourself open to mistakes doing it this way.
Consider what would happen if a new row is added to the pending queue after you have issued the INSERT SELECT but before you have started your delete.
I think you need to do this in a more controlled way inside a single loop to make sure you are only deleting what you have copied from pending into items.
$sql = "SELECT photo,title,description, name FROM pending";
$select_pending = $conn->prepare($sql);
$select_pending->execute();
$sql = "INSERT INTO items (photo,title,description, name)
VALUES (:photo,:title,:description, :name)";
$insert_items = $conn->prepare($sql);
$sql = "DELETE FROM pending WHERE id = :id";
$delete_pending = $conn->prepare($sql);
// only if you are using INNODB databases.
//$conn->beginTransaction();
while( $row = $select_pending->fetch_object() ) {
$insert_items->bindParam(':photo', $row->photo, PDO::PARAM_STR);
$insert_items->bindParam(':title', $row->title, PDO::PARAM_STR);
$insert_items->bindParam(':description', $row->description, PDO::PARAM_STR);
$insert_items->bindParam(':name', $row->name, PDO::PARAM_STR);
$insert_items->execute();
$delete_pending->bind_param(':id', $row->id, PDO::PARAM_INT);
$delete_pending->execute();
}
// only if you are using INNODB databases.
//$conn->commit();
$sql = "INSERT INTO items (photo,title,description, name)
SELECT photo,title,description, name FROM pending";
remove the () in the SELECT statement.

PDOStatement->prepare and PDOStatement->bindParam() combination not working [duplicate]

This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 8 years ago.
I have some code that should loop through values and change entries in a table. The 5 values of the variables $change_val, $column, and $id all echo out correctly, so I assume there is something wrong with my usage of bindParam (but I am not sure what it is).
$connection = new PDO("mysql:host=localhost;dbname=logbook", $username, $password);
$perform_edit = $connection->prepare("UPDATE contacts SET :column = :value WHERE name_id = :name_id");
[Definition of Arrays]
for ($i = 1; $i <= 5; $i++) {
if (!empty($_POST[ $change_array[$i]])) {
$change_val = $_POST[$change_array[$i]];
$column = $column_array[$i];
$id = $_POST["name_id_ref"];
$perform_edit->bindParam(":column", $column, PDO::PARAM_STR);
$perform_edit->bindParam(":value", $_POST[$change_array[$i]], PDO::PARAM_STR);
$perform_edit->bindParam(":name_id", $_POST["name_id_ref"], PDO::PARAM_INT);
$perform_edit->execute();
}
}
The $_POST statement is there because the value I want is actually passed from another file. When I place appropriate echo statements within the loop, though, they all print out their correct value.
I've also tried bindValue, but that did not work either. I see no errors and things at least compile smoothly—just not as they should. Nothing in the table is changed.
What's wrong here?
You cannot use place holders for table or column names it would defeat the purpose of preparing a statement ahead of time if the structure of that statement changed.
You would need to pre-build your prepare statement with the correct column names, whether you name them by hand, string replacement, or implode a list of column names.
I don't have an environment to test on right now but something like:
//Some random values and DB column names
$arrLocation = array ('Victoria','Washington','Toronto','Halifax','Vancouver');
$arrName = array ('Sue', 'Bob', 'Marley', 'Tim', 'Fae');
$arrColumn = array (1 => 'name', 2 => 'age', 3 => 'location');
/* Build column & named placeholders
* $strSet = '`name` = :name, `age` = :age, `location` = :location';
*/
$strSet = '';
foreach ($arrColumn as $column) {
$strSet .= "`$column` = :$column, ";
}
$strSet = rtrim($strSet, ', ');
$connection = new PDO($dsn, $user, $pass);
/*
* Prepared statement then evaluates to:
* UPDATE `table` SET `name` = :name, `age` = :age, `location` = :location
* WHERE `id` = :id;
*/
$stmt = $connection->prepare("UPDATE `table` SET $strSet WHERE `id` = :id;");
$arrChange = array (
1 => $arrName[(rand(0, count($arrName)-1))],
2 => rand(0, 30),
3 => $arrLocation[(rand(0, count($arrLocation)-1))]
);
$idToUpdate = 1;
$stmt->bindParam(':id', $idToUpdate, PDO::PARAM_INT);
foreach($arrChange as $key=>$value) {
$stmt->bindValue(":$arrColumn[$key]", $value);
}
$stmt->execute();

How can I properly use a PDO object for a parameterized SELECT query

I've tried following the PHP.net instructions for doing SELECT queries but I am not sure the best way to go about doing this.
I would like to use a parameterized SELECT query, if possible, to return the ID in a table where the name field matches the parameter. This should return one ID because it will be unique.
I would then like to use that ID for an INSERT into another table, so I will need to determine if it was successful or not.
I also read that you can prepare the queries for reuse but I wasn't sure how this helps.
You select data like this:
$db = new PDO("...");
$statement = $db->prepare("select id from some_table where name = :name");
$statement->execute(array(':name' => "Jimbo"));
$row = $statement->fetch(); // Use fetchAll() if you want all results, or just iterate over the statement, since it implements Iterator
You insert in the same way:
$statement = $db->prepare("insert into some_other_table (some_id) values (:some_id)");
$statement->execute(array(':some_id' => $row['id']));
I recommend that you configure PDO to throw exceptions upon error. You would then get a PDOException if any of the queries fail - No need to check explicitly. To turn on exceptions, call this just after you've created the $db object:
$db = new PDO("...");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
I've been working with PDO lately and the answer above is completely right, but I just wanted to document that the following works as well.
$nametosearch = "Tobias";
$conn = new PDO("server", "username", "password");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $conn->prepare("SELECT `id` from `tablename` WHERE `name` = :name");
$sth->bindParam(':name', $nametosearch);
// Or sth->bindParam(':name', $_POST['namefromform']); depending on application
$sth->execute();
You can use the bindParam or bindValue methods to help prepare your statement.
It makes things more clear on first sight instead of doing $check->execute(array(':name' => $name)); Especially if you are binding multiple values/variables.
Check the clear, easy to read example below:
$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname LIMIT 1");
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname', 'Bloggs');
$q->execute();
if ($q->rowCount() > 0){
$check = $q->fetch(PDO::FETCH_ASSOC);
$row_id = $check['id'];
// do something
}
If you are expecting multiple rows remove the LIMIT 1 and change the fetch method into fetchAll:
$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname");// removed limit 1
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname', 'Bloggs');
$q->execute();
if ($q->rowCount() > 0){
$check = $q->fetchAll(PDO::FETCH_ASSOC);
//$check will now hold an array of returned rows.
//let's say we need the second result, i.e. index of 1
$row_id = $check[1]['id'];
// do something
}
A litle bit complete answer is here with all ready for use:
$sql = "SELECT `username` FROM `users` WHERE `id` = :id";
$q = $dbh->prepare($sql);
$q->execute(array(':id' => "4"));
$done= $q->fetch();
echo $done[0];
Here $dbh is PDO db connecter, and based on id from table users we've get the username using fetch();
I hope this help someone, Enjoy!
Method 1:USE PDO query method
$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
Getting Row Count
$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
Method 2: Statements With Parameters
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->execute(array($name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Method 3:Bind parameters
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
**bind with named parameters**
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
or
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->execute(array(':name' => $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Want to know more look at this link
if you are using inline coding in single page and not using oops than go with this full example, it will sure help
//connect to the db
$dbh = new PDO('mysql:host=localhost;dbname=mydb', dbuser, dbpw);
//build the query
$query="SELECT field1, field2
FROM ubertable
WHERE field1 > 6969";
//execute the query
$data = $dbh->query($query);
//convert result resource to array
$result = $data->fetchAll(PDO::FETCH_ASSOC);
//view the entire array (for testing)
print_r($result);
//display array elements
foreach($result as $output) {
echo output[field1] . " " . output[field1] . "<br />";
}

Categories