Does anyone have best practices when inserting an array into a database? I've used foreach loops with success in the past, as well as various array functions. Is there a better way?
Here is a sample code:
public function InsertRequests($id) {
$db = Database::getHandler();
$selected_requests = $this->GetRequests($this->allrequests);
foreach($selected_requests as $requestid) {
$sql = "INSERT INTO requests (userid,requestid,date) VALUES (?,?,NOW())";
$stmt = $db->prepare($sql);
$stmt->bindParam(1,$id,PDO::PARAM_STR);
$stmt->bindParam(2,$requestid,PDO::PARAM_STR);
$stmt->execute();
}
return true;
}
}
You can insert multiple records with a single query like this:
INSERT INTO TABLENAME ( fieldOne, fieldTwo, fieldThree ) VALUES
( 'Jack', 'Nickholson', 'M' ),
( 'Audrey', 'Hepburn', 'F' ),
( 'Salvador', 'Dali', 'M' )
...
So, prepare your INSERT syntax iterating over your data array in a regular loop or using custom query builder than execute it once. Better practice is using an ORM library like #Karoly's said.
Related
I'm having trouble with a PDO insert.
I'd like to insert a multidimensional array into a db, which i managed to.
However, i also would like to insert a completely different array, disconnected from the first one into the same db line (which means same INSERT query).
1st multidimensional array = $_POST['training']
2nd array = $training_diploma
Kinda difficult to explain. Here is the code :
$id = "1";
$training_diploma = ("master", "bachelor");
$id_training_key = $id_training_key = $id.'_'.$training_diploma; (return: 1_master)
$sql = "INSERT INTO users_resumes (id,resume_category,id_training_key,training_diploma,training_school,training_level,training_start_date,training_end_date) VALUES ($id,'Training',$id_training_key,:training_diploma,:training_school,:training_level,:training_start_date,:training_end_date)";
$stmt= $pdo->prepare($sql);
foreach($_POST['training'] as $params){
$stmt->execute($params);
}
Any help is very welcome !!! Thx a looot !
You need to iterate the $training_diploma array as well as the $_POST array. It would be better to also include the id and id_training_key as parameters in your query so you don't have to prepare a new query for each set of values:
$id = "1";
$training_diploma = array("master", "bachelor");
$sql = "INSERT INTO users_resumes (id,resume_category,id_training_key,training_diploma,training_school,training_level,training_start_date,training_end_date) VALUES (:id,'Training',:id_training_key,:training_diploma,:training_school,:training_level,:training_start_date,:training_end_date)";
$stmt= $pdo->prepare($sql);
foreach($_POST['training'] as $params) {
foreach ($training_diploma as $diploma) {
$stmt->execute(array_merge($params, array('id' => $id, 'id_training_key' => $id . '_' . $diploma)));
}
}
I have this array
$REV = Array
(
0 => 240,
1 => 241,
2 => 242,
3 => 243,
4 => 249
);
and i'm using this code bellow to insert for now, stored each array's element in a row with $id, $userID, Type and Date
if (!empty($REV)) {
foreach ($REV as $val_rev) {
$values_rev[] = "('" . $ID . "','REV','" . $val_rev . "','" . $IDUSER . "',GETDATE())";
}
$values_rev_insert = implode(',', $values_rev);
$query_rev = "insert into dbo.CCLine (ID,CCType,CSID,IdUSer,DateCreated)values" . $values_rev_insert;
mssql_query($query_rev);
}
But what i want is can use this stored procedure but i dont have idea how to make to insert in one time using the sp:
$stmt = mssql_init('sp_insertRev');
mssql_bind($stmt, '#ID', $ID, SQLINT4);
mssql_bind($stmt, '#CCType', 'REV', SQLVARCHAR);
The array does not work here
mssql_bind($stmt, '#CSID', $val_rev, SQLINT4);//An example
mssql_bind($stmt, '#IdUSer', $IDUSER, SQLCHAR);
$result = mssql_execute($stmt);
How can i use this SP with the array
CREATE PROCEDURE [dbo].[sp_HCCInsert]
#ID int
,#CCType varchar(10)
,#CSID varchar(10)
,#IdUSer char(15)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CCID as INT
INSERT INTO [dbo].[CCLine]
([ID]
,[CCType]
,[CSID]
,[IdUSer]
,[DateCreated])
VALUES
(#ID
,#CCType
,#CSID
,#IdUSer
,GETDATE())
SET #CCID = ##IDENTITY
Select #CCID as CCID
END
I've found solution to your problem in this post
It's all about passing the array as XML string which is passed to the procedure and in procedure it is used in INSERT SELECT statement with OPENXML function.
CREATE PROCEDURE [dbo].[sp_HCCInsert]
(
#XMLDoc XML
)
Then use function OPENXML in MSSQL. You should read this topic.
So pseudo code will look like
INSERT ... SELECT OPENXML(#XML...)
After you read it and fit to your needs just pass XML to procedure.
Some useful links about OPENXML
http://msdn.microsoft.com/pl-pl/library/ms175160.aspx
Using OPENXML in SQL Server 2008 stored proc - INSERT order differs from XML document
http://www.informit.com/articles/article.aspx?p=26499
Moreover, I'd suggest using PDO because it has better abstract layer. I hope that it helped you.
I tend to use PDO instead of the mssql_* functions, you can still use dblib and you can bind that array quite simply. One thing though, you have 5 elements in that array but only 4 input variables to your stored procedure. This example will assume you only have 4 elements in your array.
$sql = "EXEC sp_HCCInsert ?, ?, ?, ?"; // SQL string with ? where params should go
$pdh = new PDO("dblib:host=somthing.somewhere\\INSTANCENAME;port=1433;dbname=MyDatabase;","username","password");
$sth = $pdh->prepare($sql); // Prepare query
$sth->execute($REV); // Execute and bind non-associative array
The only caution with using the PDO with dblib on PHP 5.3 or before, it goes and does a prefetch on execute. So if you execute a huge query and you want to loop through each record one at a time... sorry, you get the whole thing buffered first.
Also, you can use an associative array if you'd like
$REV = array(":ID" => 240, ":CCType" => 241, ":CSID" => 242, ":IdUSer" => 243);
$sql = "EXEC sp_HCCInsert :ID, :CCType, :CSID, :IdUSer"; // SQL string with named params
$pdh = new PDO("dblib:host=somthing.somewhere\\INSTANCENAME;port=1433;dbname=MyDatabase;","username","password");
$sth = $pdh->prepare($sql); // Prepare query
$sth->execute($REV); // Execute and bind associative array
The best part is, the execute method for the PDO::Statement escapes strings! Safety first you know.
$sql = "INSERT INTO table column(c1,c2)
VALUES('d1','d2'),('dd1','dd2'),('ddd1','ddd2')";// this is the basic sql command
$data = array('data1','data2','data3');
$data = '('.implode(', ',$data).')';
$sql = "INSERT INTO table column(c1,c2) VALUES $data";
$data = array(array('1','2','3'),array('4','5','6'),array('7','8','9'));
$xa = array();
$a = 0;
foreach($data as $dt)
{
$xa[$a] = '('.implode(',',$dt).')';
++$a;
}
$data = '('.implode(',',$xa).')';
$sql = "INSERT INTO table column(c1,c2) VALUES $data";
I'm using MySQLi for a project (but could easily switch to PDO, read the edit at the bottom). What I want is to be able to process an associative array into an mysql query without typing every key/value pair manually. I know that might be simply put, but I'm still in a learning process when it comes to MySQLi/PDO. To make it clear what I mean here is an example:
Let's say I have this associative array:
$data = array(
'name' => 'Objective',
'short_name' => 'OB',
'generation' => 1
);
What I want is to create a query like this:
UPDATE signals SET ? = ? WHERE sid = '1'
And it to become a query like this (or instead of an UPDATE, an INSERT, SELECT etc.):
UPDATE signals SET
name = 'Objective',
short_name = 'OB',
generation = 1
WHERE sid = '1'
So basically my question is: is this possible with MySQLi or PDO itself? If it's possible how would I have to do this?
I've read on preparing statements before executing, but it's not getting to me yet. Hopefully someone can help me out.
Edit: I'm still very early into the project so i'm also fine with using PDO, but the same question remains. I did look into both PDO and mysqli, and I'm not sure how to do it with PDO either. So for the sake of the question i'll add PDO to as a tag and to the question.
Here is a function that will take an input array and produce something you can drop straight into your query, as long as you are only updating a single table:
function array_to_pdo_params($array) {
$temp = array();
foreach (array_keys($array) as $name) {
$temp[] = "`$name` = ?";
}
return implode(', ', $temp);
}
Now you can perform your PDO query like this:
// The data
$data = array(
'name' => 'Objective',
'short_name' => 'OB',
'generation' => 1
);
// The parameter for the WHERE clause
$sid = 1;
// Build the query string
$query = "
UPDATE `signals`
SET ".array_to_pdo_params($data)."
WHERE `sid` = ?
";
// Convert the data array to indexed and append the WHERE parameter(s) to it
$queryData = array_values($data);
$queryData[] = $sid;
$stmt = $db->prepare($query); // Obviously add the appropriate error handling
$stmt->execute($queryData);
You can use the PDO's execute statement by passing an array of input values, for a prepared query. For reference: http://php.net/manual/en/pdostatement.execute.php
Example:
<?php
/* Execute a prepared statement by passing an array of insert values */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
?>
Zend_DB will let you do exactly that.
Tho we created a wrapper over it my work to make it simpler, I really think it's as simple as you can get, and it does all the magical stuff for you.
You really should give it a try; big time saver once you learn it.
How about building the query with http_build_query as follows:
$columns = array(
'name',
'short_name',
'generation', ...
);
$data = array(
'name' => 'Objective',
'short_name' => 'OB',
'generation' => 1
);
$to_update = array_intersect_key($data, array_flip($columns));
$update_string = urldecode(http_build_query(array_combine(array_keys($columns), array_fill(0, count($columns), '?')), '', ', '));
try {
$stmt = $db->prepare(sprintf('UPDATE table SET %s WHERE condition=?', $update_string));
$result = $stmt->execute(array_values($data));
...
} catch (\PDOException $ex) {
}
Be sure to have the parameter for the WHERE condition at the end of your $data array.
I tried to find another question with the answer to this but I've had no luck. My question is basically...will this work?
$insert_tweets = "INSERT INTO tweets (
'id',
'created_at',
'from_user_id',
'profile_image',
'from_user',
'from_user_name',
'text'
) VALUES (
{$user_data[$i]["id"]},
{$user_data[$i]["created_at"]},
{$user_data[$i]["from_user_id"]},
{$user_data[$i]["profile_image"]},
{$user_data[$i]["from_user"]},
{$user_data[$i]["from_user_name"]},
{$user_data[$i]["text"]}
)"
for($i=0;$i<count($user_data);$i++){
mysqli_query($mysqli,$insert_tweets);
}
$user_data is a multi-dimensional array, the first level of which is numeric, the subsequent level is associative.
Also, what would be the best way to "database prepare"/sanitize the associative array variables prior to insertion? I don't anticipate any malicious data but it is always possible.
for($i=0;$i<count($user_data);$i++){
$insert_tweets = "INSERT INTO tweets ('id','created_at','from_user_id','profile_image','from_user','from_user_name','text') VALUES ({$user_data[$i]["id"]},{$user_data[$i]["created_at"]},{$user_data[$i]["from_user_id"]},{$user_data[$i]["profile_image"]},{$user_data[$i]["from_user"]},{$user_data[$i]["from_user_name"]},{$user_data[$i]["text"]})";
mysqli_query($mysqli,$insert_tweets);
}
This should work
Yes, it will work, but the best way to do this would be to use PDO.
You can create nameless parameters in your prepare statement and then just pass in a array to bind values to those params.
$data = array('val1', 'val2');
$query = $db->prepare("INSERT INTO table (col1, col2) VALUES (? , ?)");
$query->execute($data);
PDO will escape the input values for you.
Here's a tutorial on PDO to get you started
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/
Here is my suggestion on sanitizing your array:
What i do is create a basic function for sanitizing data:
function array_sanitize(&$item){
$item = mysql_real_escape_string($item);
}
Then you can use the array_walk() to sanitize your array with your new function. (php manual refrence)
and sanitize by passing in your array like this:
array_walk($user_data, 'array_sanitize');
I have a php function getContactList():
$res = getContactList(trim($_POST['username']), trim($_POST['password']));
which returns this array:
$contactList[] = array('name' => $name, 'email' =>$email);
I need to store the contents of this array into a MySQL database.
Somehow can i store the entire contents of the array in the database at one go ??
The number of array items will be more than 500 at each go , so i wanna avoid the usual looping practice and calling the "Insert" statement in the for loop as this will need a long time to execute.
Note: I need to store the results in separate columns - One for Name and another for Email. With 500 items in that array I need to have 500 rows inserted - one Name-Email pair per row.
$values = array();
// the above array stores strings such as:
// ('username', 'user#domain.com')
// ('o\'brien', 'baaz#domain.com')
// etc
foreach($contactList as $i => $contact) {
$values[] = sprintf(
"('%s', '%s')",
mysql_real_escape_string($contact['name'], $an_open_mysql_connection_identifier),
mysql_real_escape_string($contact['email'], $an_open_mysql_connection_identifier)
);
}
$query = sprintf(
"INSERT INTO that_table(name, email) VALUES %s",
implode(",", $values)
);
If you are trying to insert many rows, i.e. run the same query many times, use a prepared statement.
Using PDO, you can do this:
// prepare statement
$stmt = $dbh->prepare("INSERT INTO contacts (email, name) VALUES (:email, :name);");
// execute it a few times
foreach($contactList as $contact) {
$stmt->bindValue(':email', $contact['email'], PDO::PARAM_STR);
$stmt->bindValue(':name', $contact['name'], PDO::PARAM_STR);
$stmt->execute();
}
PDO will also take care of proper string escaping.
use the standard php serialize function
$serData_str = serialize($contactList);
then save it in the DB
after reading your data from DB simply unserialize it
$myData_arr = unserialize($serContactList);
In the loop you can create an insert statement and execute it after the loop. the insert statement will include all content.
The statement would look like
INSERT INTO employee (name) VALUES ('Arrayelement[1]'),('Arrayelement[2]'), ('Arrayelement[3]'),('Arrayelement[4]');