I would like to know how to efficiently update multiple rows of data with the UPDATE statement. I know I can insert multiple records like this one below.
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');
But how it works in Update, or if I have to loop the query and update one by one?
At the moment I have to use foreach to loop and update each SQL statement.
foreach() {
// update statement....
// and execute the query
}
You can use case when indise update..
An eg:
UPDATE users
SET value = CASE
WHEN id in (1,4) THEN 53
WHEN id = 2 THEN 65
WHEN id in (3,5) THEN 47
END
WHERE id IN (1,2,3,4,5)
Refer this so and this for more.
$data = array(
array(
100,
'Name 1',
'Value 1',
'Other 1'
),
array(
101,
'Name 2',
'Value 2',
'Other 2',
)
array(
102,
'Name 3',
'Value 3',
'Other 3'
)
)
for($i = 0; $i < count($data); $i++) {
for($j= 0; $j< count($data[$i]); $j++) {
$field1 = $data[$i][$j];
$field2 = $data[$i][$j];
$filed3 = $data[$i][$j];
$field4 = $data[$i][$j];
query("UPDATE TABLE SET.... WHERE id = $field1");
}
}
You can use CASE in MYSQL also:
Ex:
UPDATE example
SET example_id = CASE
WHEN example_id=100 THEN 1000
WHEN example_id=101 THEN 1001
WHEN example_id=102 THEN 1002
ELSE example_id*10
END
You can see another example, In this, there is a table Person and having wrongly entered Gender. So you need to correct them by updating Male to Female and Female to Male.
So here is your code:
UPDATE Person
SET Gender= CASE
WHEN gender= 'Male' THEN 'Female'
WHEN gender= 'Female' THEN 'Male'
ELSE gender
END
Related
Does anybody has an idea how to multiple insert depending on a variable?
$diff = abs(strtotime($datumtot) - strtotime($datumvan));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24) / (60*60*24));
Here i get the result back it can be 1 to 14.
now i want to insert it into the database.
My insert statement is a follows lets say days == 3
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'),
is there a better way to do it? to check on the variable and then insert it how much it is?
thanks
I'm trying to unit test methods in isolation that work with csv files, using vsf-stream from here: https://github.com/mikey179/vfsStream
I've created a 2 dimensional data array to test, but when I try to add this to the mocked file it seems to parse the newline characters, instead of adding new lines. I've tried both fputcsv and fputs but both have the same results. Using the same data and php functions I can write successfully to a normal file, the issues seems to be with vfs-stream. Not much documentation on the net and completely lost:
$this->data = array(
array( 'col1', 'col2', 'col3', 'col4' ),
array( 'row 0 1', 'row 0 2', ' row 0 3', ' row 0 4' ),
array( 'row 1 1', 'row 1 2', ' row 1 3', ' row 1 4' ),
array( 'row 2 1', 'row 2 2', ' row 2 3', ' row 2 4' ),
array( 'row 3 1', 'row 3 2', ' row 3 3', ' row 3 4' ),
array( 'row 4 1', 'row 4 2', ' row 4 3', ' row 4 4' ),
array( 'row 5 1', 'row 5 2', ' row 5 3', ' row 5 4' ),
);
$this->root = vfsStream::setup('test-dir');
$file = vfsStream::url('test-dir/foo.csv');
$handle = fopen($file, "a+");
foreach( $this->data as $arr)
fputcsv($handle, $arr, "|"); //$content .= implode("|", $arr) . "\n";
The above code will produce the mocked file but without any newline characters, so parsing the mocked csv file later in the test won't work as it seems to all be written in the one long line:
var_dump( file_get_contents( $file ) );
will produce:
string(272) "col1|col2|col3|col4\n"row 0 1"|"row 0 2"|" row 0 3"|" row 0 4"\n"row 1 1"|"row 1 2"|" row 1 3"|" row 1 4"\n"row 2 1"|"row 2 2"|" row 2 3"|" row 2 4"\n"row 3 1"|"row 3 2"|" row 3 3"|" row 3 4"\n"row 4 1"|"row 4 2"|" row 4 3"|" row 4 4"\n"row 5 1"|"row 5 2"|" row 5 3"|" row 5 4"\n"
I'm hoping that I'm missing a flag for this and its not a bug. Any help appreciated, cheers.
The issue was using var_dump instead of print or echo to see the results. var_dump will give a descriptive and literal representation of the variable and not parse the \n chars - print or echo would print and parse the \n chars.
Therefore the above code works and its my stupidity or lack of sleep that is the issue.
I am trying to write php code which takes an NSArray of NSDictionaries and adds the records to a database. Unfortunately, this is taking around 20 seconds to process around 500 records with a total size of around 2mb.
function uploadTracks($tracks, $partyID, $pName) {
$tracks = json_decode($tracks, true);
$itemInfo = array();
foreach($tracks as $itemInfo){
$track = $itemInfo['songTitle'];
$artist = $itemInfo['artistName'];
$album = $itemInfo['albumName'];
$artwork = $itemInfo['artwork'];
$result = query("INSERT INTO partyRecords(Pkey,songName,songArtist,imageBinary,partyName) VALUES ('%s','%s','%s','%s','%s')" ,$partyID,$track,$artist,$artwork,$pName);
}
}
Is there anyway to optimize the above code? Could json_decode be what is taking the most time?
You can insert multiple records in single insert query. In this case your db indexes will be updated once and it gain you performance boost:
INSERT INTO partyRecords
(Pkey, songName, songArtist, imageBinary, partyName)
VALUES
(1, 'Name 1', 'Artist 1', 'Image 1', 'Party 1'),
(2, 'Name 2', 'Artist 2', 'Image 2', 'Party 2'),
(3, 'Name 3', 'Artist 3', 'Image 3', 'Party 3'),
(4, 'Name 4', 'Artist 4', 'Image 4', 'Party 4');
I would say 95% it is the queries. You need to compile the queries and insert them 100 or so at a time. It would be best to escape the query variables yourself (mysql: mysql_real_escape_string() ).
INSERT INTO partyRecords(Pkey,songName,songArtist,imageBinary,partyName) VALUES (2,'12312','12312321','12312332423','23423432');INSERT INTO partyRecords(Pkey,songName,songArtist,imageBinary,partyName) VALUES (2,'12312','12312321','12312332423','23423432');...
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.