MySQL trigger keeps adding two rows for every update - php

I am trying to update a 'ticketHistory' table after every update of my 'tickets' table. I have the following trigger set up to run whenever my 'tickets' table is updated (usually when a field is edited):
TRIGGER `ticket_edit` AFTER UPDATE ON `tickets` FOR EACH ROW INSERT INTO ticketHistory
(ticketId, action, originator, assigned, date)
VALUES
(NEW.ticketId, "Edited", NEW.userId, NEW.assigned, NEW.lastUpdated);
Whenever an update is done in my app, the field being edited is updated, as well as the 'lastUpdated' time. I think because two fields are being updated, it is running the trigger twice, resulting in two identical rows being inserted into my 'ticketHistory' table. I only want one row inserted.
Is there a way to limit it to just one row being inserted? Any help is greatly appreciated!
EDIT
All database inserts and updates are being done using CodeIgniter's ActiveRecord.
My model:
public function editTicket($ticket)
{
$q = $this->db->where('ticketId', $ticket['ticketId']);
$q = $this->db->update('tickets', $ticket);
$results = $this->db->affected_rows();
}
My Controller:
public function edit_ticket()
{
$ticketId = $this->uri->segment(3);
$description = str_replace("\n", "\r", $this->input->post('description'));
$ticket = array(
'ticketId' => $ticketId,
'headline' => $this->input->post('headline'),
'description' => $description,
'priority' => $this->input->post('priority'),
'category' => $this->input->post('category'),
'lastUpdated' => date("Y-m-d H:i:s", time())
);
$this->tickets->editTicket($ticket);
}

public function editTicket($ticket)
{
$q = $this->db->where('ticketId', $ticket['ticketId']);
echo "I am here again<br/>";
$q = $this->db->update('tickets', $ticket);
$results = $this->db->affected_rows();
}

I'm not sure why that's adding 2 different rows, but you could just make a primary key field and your DBMS wouldn't allow the duplicate.
Hope this helps!

So, as a solution, I modified my trigger as such:
TRIGGER `ticket_edit` AFTER UPDATE ON `tickets`
FOR EACH ROW
IF NEW.headline <> OLD.headline || NEW.description <> OLD.description || NEW.priority <> OLD.priority
THEN
INSERT INTO ticketHistory
(ticketId, action, originator, assigned, date)
VALUES
(NEW.ticketId, "Edited", NEW.userId, NEW.assigned, NEW.lastUpdated);
END IF
By adding the conditionals, I think it only activated the trigger once, resulting in only one row being inserted.
Hope this helps someone!

Related

I want affected rows data and column which has affected by update query in codeigniter

Is there a way to obtain only the affected columns after an update query?
After an update query, that involves 10 columns, I know that only 2 columns are
really updated (because the values of the other cols don't change).
I need to know the names of the changed cols, for logging purpose.
$this->db->query("UPDATE `table1` SET name = $name,......................,column10=10 WHERE id=$id")->result();
$this->db->affected_rows();
This code gives number of affected rows but i want the data and updated
column information.
As far as I know there are no built-in CodeIgniter functionality for that. You could compare old value with new value though :
$last_record = $this->db->get_where('table1', array('id' => $id))->row_array();
$this->db->query("UPDATE `table1` SET name = $name,......................,column10=10 WHERE id=$id")->result();
// $this->db->affected_rows();
$new_record = $this->db->get_where('table1', array('id' => $id))->row_array();
$affected_columns = array_diff($new_record, $last_record);
foreach ($affected_columns as $field => $value) {
echo "[field] : $field\r\n";
echo "[old_value] : $last_record[$field]\r\n";
echo "[new_value] : $value\r\n";
echo "\r\n";
}
This will print each of the of the updated column with it's old-new value respectively.

Transaction rollback function not work in Codeigniter

when i run this code data insert in 3 tables successfully and commit when in give the error in in 3rd table insert query then data insert in 1st and 2nd table and not in 3rd table and also not RollBack function work properly. I want do when 3rd table query not work then 1st and 2nd table insert data will remove and delete.
$this->db->trans_start(TRUE);
// 1st table insert query
$this->db->insert('users',$userInfo);
$userId = $this->db->insert_id();
$query = $this->db->query("SELECT `roleId` FROM `role` WHERE roleName='Clint';");
foreach ($query->result_array() as $row)
{ $roleId = $row['roleId']; }
$user_role = array( 'user_id' => $userId, 'role_id' => $roleId );
// 2nd table insert query
$this->db->insert('user_role', $user_role);
$city_id += [ "projectInfo" => $userId ];
// 3rd table insert query
$this->db->insert('project', $projectInfo);
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE )
{
echo "Flase";
$this->db->trans_rollback();
}
else
{
echo "True";
$this->db->trans_rollback();
}
You are manually rolling back transactions! In this case, you should use
$this->db->trans_begin(); NOT $this->db->trans_start();
CI automatically rolls back transactions, you dont need do it manually.
If you use $this->db->trans_start, you dont need $this->db->trans_rollback().
Comment out $this->db->trans_rollback(), or leave those and use $this->db->trans_begin(), then check results.
https://www.codeigniter.com/user_guide/database/transactions.html
Good luck!

2 sequence query update in 1 function Model Laravel

I have this query update that needs 2 sequence to complete the job. It's like this :
Model:
$result = DB::statement( DB::raw("SET #a:=0;") );
$numbering = DB::update(DB::raw(UPDATE table SET number:= #a+1, table_number = number+1 ));
return $numbering;
if i executed that function, only the number column is filled with value #a+1 , but the table_number column is still blank. I have to run the function twice in controller to get table_number column filled with the values number+1
The number column isn't yet set at the time of the first update so use
UPDATE table SET number:= #a+1, table_number = #a+2

Add new user and usermeta into database with SQL

I've using this to create a new user in the WordPress database...
// Add user to WP users table.
$user_table_name = $wpdb->prefix . "users";
$unique_string = substr(md5(rand(0, 1000000)), 0, 10);
$wpdb->insert( $user_table_name, array(
'user_login' => sanitize_text_field($_POST['email']),
'user_pass' => sanitize_text_field(MD5($unique_string)),
'user_email' => sanitize_text_field($_POST['email']),
'user_registered' => sanitize_text_field(date("Y-n-d G:i:s")),
'user_status' => $_POST['1'],
'display_name' => sanitize_text_field($_POST['first_name']) . " " . sanitize_text_field($_POST['last_name'])
) );
...which works fine, and let's pretend that the ID of that user turned out to be 1234 in the database table (thanks to auto increment).
So now I also need to add the corresponding user meta information into the usermeta table for that user, and this is where I get a little confused.
The code above is easy because it's just adding a row to a table. But the usermeta table is different because it will need - in this case - a bunch of rows with the corresponding user_ID of 1234 each respectively with:
nickname (I'll use the email address for this)
wp_capabilities (value to be a:1:{s:10:"subscriber";b:1;})
sales (a custom field I have - value will be set to the word "yes")
colour (another custom field I have - value will be set to the word "green")
I'm guessing the SQL statement is going to be similar to the one at the start of this post.
If anyone could show me, that would be awesome.
UPDATE:
So this is mostly done. This works:
// Add corresponding user metadata to WP users table.
$usermeta_table_name = $wpdb->prefix . "usermeta";
$last_id = $wpdb->insert_id;
$role = sanitize_text_field('a:1:{s:10:"subscriber";b:1;}');
$wpdb->query(
$wpdb->prepare(
"
INSERT INTO $usermeta_table_name (
`umeta_id`,
`user_id`,
`meta_key`,
`meta_value` )
VALUES (
NULL,
$last_id,
$usermeta_table_name . 'capabilities',
'$role' )
",
$last_id, $last_id
)
);
That will add one row to the usermeta table, but how can I add 2 more rows within the same statement?
Store the last inserted row's ID to a variable:
$last_id = $wpdb->insert_id;
now, use this $last_id variable for metadata insertion. The insert_id variable is provided by the wpdb class.
OK so I feel a little silly about this - though to be fair it's been a long time since I wrote any SQL :-)
The answer is simply to follow this method:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

Cakephp system for update the row for given id if no id exists, create a new row

What is do you think is the best way to create a procedure where request is made and if there are any existing id in the database, update if not create a new one.
I was using something like below and it seems to work but is there are better way?
$id = $this->User->findByFacebookId($facebook);
if($id){
$this->User->set(array(
'facebook_id' => $facebook,
'longitude' => $longitude,
'latitude' => $latitude,
'firstname' => $firstname,
'surname' => $surname
));
$this->User->id = $id['User']['id'];
$this->User->save($this->data);
Yup, CakePHP basically does this by default. If your data has no id field an INSERT statement is issued, whereas if there is an id field it issues UPDATE ... WHERE ID = ?.
Just to show how simply this can be done, below is a way to do the same without even calling Model::set() or updating the Model::id property:
// get existing record (so we can get value of `id` field)
$existing = $this->User->findByFacebookId($facebook);
// if record exists, map data to correct record `id`
if ($existing) {
$this->data['User']['id'] = $existing['User']['id'];
}
// save data to table (`id` determines if INSERT or UPDATE)
$this->User->save($this->data);

Categories