kindly enlightened me, which is faster/better approach or just the same between CI batch insert and loop insert.
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name' ,
'date' => 'My date'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name' ,
'date' => 'Another date'
)
);
batch insert:
$this->db->insert_batch('mytable', $data);
/* produces: INSERT INTO mytable (title, name, date)
VALUES ('My title', 'My name', 'My date'),
('Another title', 'Another name', 'Another date'); */
loop insert (php):
for( $i = 0; $ < count($data); $i++ )
{
INSERT INTO mytable (title, name, date)
VALUES ($data[$i]['title'], $data[$i]['name'], $data[$i]['date'])
}
thanks!
Batch inserts are usually faster since they process the data in once, were as the INSERT has some overhead (eg, the SQL optimizer cannot deduct certain steps). That said, you need to process a tremendous number of rows to create a notable difference.
If your curious if it would matter anyway, then don't forget to also measure the time it costs the framework to map the classes to the database table(s). There's a good chance the ORM consumes more resources than a looped SQL INSERT.
Related
Is there any way where i can run Multiple semicolon separated query in Code Igniter without insert_batch() ?
e.g:
$a = 'INSERT INTO table (a,b,c) VALUES (1,2,3); INSERT INTO table1 (x,y,z) VALUES (1,2,3);';
$this->db->query($a);
Above code gives invalid query error.
If multiple tables with single data(Using Transactions) - (N table vs 1 Data)
Running Transactions Manually
$this->db->trans_begin();
$this->db->query('INSERT INTO table (a,b,c) VALUES (1,2,3)');
$this->db->query('INSERT INTO table1 (x,y,z) VALUES (1,2,3)');
if ($this->db->trans_status() === FALSE)
{
$this->db->trans_rollback();
}
else
{
$this->db->trans_commit();
}
Running Transactions Automatically
$this->db->trans_start();
$this->db->query('INSERT INTO table (a,b,c) VALUES (1,2,3)');
$this->db->query('INSERT INTO table1 (x,y,z) VALUES (1,2,3)');
$this->db->trans_complete();
If inserting Single table with multiple data (1 table vs N Data)
$data = array(
array(
'a' => 'My title 1' ,
'b' => 'My Name 1' ,
'c' => 'My date 1'
),
array(
'a' => 'My title 2' ,
'b' => 'My Name 2' ,
'c' => 'My date 2'
)
);
$this->db->insert_batch('mytable', $data);
I am applying this query:
$this->db->select_max('product_id');
$this->db->from('products');
$query=$this->db->get();
return $query->result();
to get max value from table.
But when i add this result to db in another table. like this:
$this->db->insert('images',$product_id);
It show this error:
Error Number: 1054
Unknown column 'Array' in 'field list'
INSERT INTO `images` (`product_id`) VALUES (Array)
Filename: C:\wamp\www\system\database\DB_driver.php
Line Number: 330
I am using codeigniter.
You are applying an array within input here's I have updated your code
Model Code
$this->db->select_max('product_id');
$this->db->from('products');
$query=$this->db->get();
return $query->result_array();
Controller Code
$product_id = $this->Product_area_model->get_product_id();
$data['product_id'] = $product_id[0]['product_id'];
$result = $this->your_model->foo($data);
Model Code
function foo($data = ''){
$this->db->insert('images',$data);
return $this->db->insert_id();
}
Hope it will work for you...
$this->db->insert('images',$product_id[0]['product_id']);
Codeigniter allows you to specify an array of values as the data to insert, but I think your issue is that you're inserting an array of arrays.
If that's the case then use the batch function...
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name' ,
'date' => 'My date'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name' ,
'date' => 'Another date'
)
);
$this->db->insert_batch('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'), ('Another title', 'Another name', 'Another date')
Given this type of User table structure where you are storing many User values (such as phone #'s, preferences, contact info) in a table:
Table: User ID | Key | Value
$values = [
1 => 'A value for key 1',
2 => 'Hello',
8 => 'Meow',
]
// Update values
$stmt = $pdo_db->prepare('
INSERT INTO table (UID, KEY, VALUE)
VALUES (:UID, :KEY, :VALUE)
ON DUPLICATE KEY UPDATE VALUE = :VALUE');
foreach ($values as $key => $value) {
$stmt->bindParam(':KEY', $key);
$stmt->bindParam(':VALUE', $value);
$stmt->execute();
}
If you have 150 different pairs, thats 150 queries per update. How would I optimize this code? Would making a giant SQL make the work easier on the mysql side? Should I be looking at changing the structure itself?
Take this query as a guide-
INSERT INTO example
(example_id, name, value, other_value)
VALUES
(100, 'Name 1', 'Value 1', 'Other 1'),
(101, 'Name 2', 'Value 2', 'Other 2'),
(102, 'Name 3', 'Value 3', 'Other 3'),
(103, 'Name 4', 'Value 4', 'Other 4');
Allows you to insert multiple records at once.
If you know which records are new, it could speed up to separate those into a plain INSERT - mysql has to spend extra time reconciling the ON DUPLICATE... UPDATE otherwise.
Also think about using UPDATE or REPLACE if you're only updating.
This is what I have so far
Controller
$i = 0;
foreach ($this->input->post('skill') as $cat) {
$data[$i++]['skill'] = $cat;
}
$this->db->update_batch('skills', $data);
}
Model
function update_record($data)
{
$this->db->update('skills', $data);
}
View
<?php foreach ($skills as $skill):?>
<input type="text" name="skill[]" value="<?php echo $skill->skill;?>">
<?php endforeach?>
I am getting a database error
You must specify an index to match on for batch updates.
Please help me fix this I tried googling and nothing is coming up.
Ok, here is the issue.
According to the CI Docs for update_batch you need to add a third parameter that is the where key . Here is an example from the docs.
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name 2' ,
'date' => 'My date 2'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name 2' ,
'date' => 'Another date 2'
)
);
$this->db->update_batch('mytable', $data, 'title');
So, above in the queries the title column is what the row is compared to. So for the rows that have title as 'My Title' The first array element is used as update and for those with 'Another Title' the second element. I hope you understand. If we don't have a compare field then the whole database will be updated :-P
Here is the final query produced from the above operation.
UPDATE `mytable` SET `name` = CASE
WHEN `title` = 'My title' THEN 'My Name 2'
WHEN `title` = 'Another title' THEN 'Another Name 2'
ELSE `name` END,
`date` = CASE
WHEN `title` = 'My title' THEN 'My date 2'
WHEN `title` = 'Another title' THEN 'Another date 2'
ELSE `date` END
WHERE `title` IN ('My title','Another title')
Hope this helps.
I'm trying to join two associative arrays together based on an entry_id key. Both arrays come from individual database resources, the first stores entry titles, the second stores entry authors, the key=>value pairs are as follows:
array (
'entry_id' => 1,
'title' => 'Test Entry'
)
array (
'entry_id' => 1,
'author_id' => 2
I'm trying to achieve an array structure like:
array (
'entry_id' => 1,
'author_id' => 2,
'title' => 'Test Entry'
)
Currently, I've solved the problem by looping through each array and formatting the array the way I want, but I think this is a bit of a memory hog.
$entriesArray = array();
foreach ($entryNames as $names) {
foreach ($entryAuthors as $authors) {
if ($names['entry_id'] === $authors['entry_id']) {
$entriesArray[] = array(
'id' => $names['entry_id'],
'title' => $names['title'],
'author_id' => $authors['author_id']
);
}
}
}
I'd like to know is there an easier, less memory intensive method of doing this?
Is it possible you can do a JOIN in the SQL used to retrieve the information from the database rather than fetching the data in multiple queries? It would be much faster and neater to do it at the database level.
Depending on your database structure you may want to use something similar to
SELECT entry_id, title, author_id
FROM exp_weblog_data
INNER JOIN exp_weblog_titles
ON exp_weblog_data.entry_id = exp_weblog_titles.entry_id
WHERE field_id_53 = "%s" AND WHERE entry_id IN ("%s")
Wikipedia has a bit on each type of join
Otherwise the best option may be to restructure the first array so that it is a map of the entry_id to the title
So:
array(
array(
'entry_id' => 1,
'title' => 'Test Entry 1',
),
array(
'entry_id' => 3,
'title' => 'Test Entry 2',
),
)
Would become:
array(
1 => 'Test Entry 1',
3 => 'Test Entry 2',
)
Which would mean the code required to merge the arrays is simplified to this:
$entriesArray = array();
foreach ($entryAuthors as $authors) {
$entriesArray[] = array(
'id' => $authors['entry_id'],
'title' => $entryNames[$authors['entry_id']],
'author_id' => $authors['author_id']
);
}
I've rearranged some of my code to allow for a single SQL query, which looks like:
$sql = sprintf('SELECT DISTINCT wd.field_id_5, wd.entry_id, mb.email, mb.screen_name
FROM `exp_weblog_data` wd
INNER JOIN `exp_weblog_titles` wt
ON wt.entry_id=wd.entry_id
INNER JOIN `exp_members` mb
ON mb.member_id=wt.author_id
WHERE mb.member_id IN ("%s")
AND wd.entry_id IN ("%s")',
join('","', array_unique($authors)),
join('","', array_unique($ids))
);
This solves my problem quite nicely, even though I'm making another SQL call. Thanks for trying.
In response to your comment on Yacoby's post, will this SQL not give the output you are after?
SELECT exp_weblog_data.entry_id, exp_weblog_data.field_id_5 AS title_ie, exp_weblog_titles.author_id
FROM exp_weblog_data LEFT JOIN exp_weblog_titles
ON exp_weblog_data.entry_id = exp_weblog_titles.entry_id
WHERE exp_weblog_data.field_id_53 = "%S"
Every entry in exp_weblog_data where field_id_53 = "%S" will be joined with any matching authors in exp_weblog_titles, if a an entry has more than one author, two or more rows will be returned.
see http://php.net/manual/en/function.array-merge.php