DBIx::Class update only one row - mysql

I am using DBIx::Class and I would like to only update one row in my table. Currently this is how I do it:
my $session = my_app->model("DB::Session")->find(1);
$session->update({done_yn=>'y',end_time=>\'NOW()'});
It works, but the problem is that when it does find to find the row, it does this whole query:
SELECT me.id, me.project_id, me.user_id, me.start_time, me.end_time, me.notes, me.done_yn FROM sessions me WHERE ( me.id = ? ): '8'
Which seems a bit much when all I want to do is update a row. Is there anyway to update a row without having to pull the whole row out of the database first? Something like this is what I am looking for:
my_app->model("DB::Session")->update({done_yn=>'y',end_time=>\'NOW()'},{id=>$id});
Where $id is the WHERE id=? part of the query. Does anyone know how to do this? Thanks!

You can run update on a restricted resultset which only matches this single row:
my_app->model("DB::Session")->search_rs({ id=> 1 })->update({done_yn=>'y',end_time=>\'NOW()'});
I suggest you use a DateTime->now object instead of literal SQL for updating the end_time column because it uses the apps servers date and time instead of the database servers and makes your schema more compatible with different RDBMSes.

Do you have a check if the row was found to prevent an error in case it wasn't?
You might want to use update_or_create instead.

You could use the "columns" attribute:
my $session = my_app->model("DB::Session")->find(1, {columns => "id"});

Related

MySql multiple delete statements

I couldn't find anything here or google that works for me.
I have tried the following code:
delete from wms where barcode = '65025351102908' and '105077351106577';
values are a varchar bear in mind.
No errors come up, but 0 rows are affected. But they are definitely out there.
Your WHERE clause isn't working as you expect. You can't factorise conditions such way
Writting this will only remove 65025351102908 :
WHERE barcode = '65025351102908' and '105077351106577';
-- ^------------------------^ ^---------------^
-- Condition 1 Condition 2 (always true because different than a falsy value)
I suppose you want to remove both 65025351102908 and 105077351106577
This is done using a OR (remove where the id is equal to the first one OR the second one)
Try this instead :
delete from wms where barcode = '65025351102908' or barcode = '105077351106577';
If you have a lot of barecode to remove, you can use the IN operator :
delete from wms where barcode IN ('65025351102908', '105077351106577');
Are you trying to delete the two rows with those two values?
Then do this:
delete from wms
where (barcode = '65025351102908') or (barcode = '105077351106577');
You can also do this:
delete from wms
where barcode in ('65025351102908','105077351106577');
If you want to delete "between" those values (taking in mind that you are writing them inside single quotes as string) your syntax could be better like this:
delete from wms where barcode BETWEEN '65025351102908' and '105077351106577';

Statement in trigger is not "picking up" the condition in its Where clause

so I'm currently working on a MySQL trigger. I'm trying to assign values to two variables when a new record is inserted. Below are the queries:
SET mssgDocNo = (SELECT Document_ID FROM CORE_MSSG WHERE Message_ID = new.MSSG_ID);
SET mssgRegime = (SELECT CONCAT (Regime_Type, Regime_Code) FROM T_DOC WHERE CD_Message_ID = new.MSSG_ID);;
For some reason, the second SQL query is not picking up the 'new.MSSG_ID' condition while the first query in same trigger recognizes it. I really can't figure out what seems to be the problem.
When I replace the 'new.MSSG_ID' with a hard-coded value from the database in the second query it seems to work. I doubt the 'new.MSSG_ID' is the problem because it works perfectly fine in the first query.
I've tried pretty much anything I could think of. Would appreciate the help.
I would write these more simply as:
SELECT mssgDocNo := Document_ID
FROM CORE_MSSG
WHERE Message_ID = new.MSSG_ID;
SELECT mssgRegime := CONCAT(Regime_Type, Regime_Code)
FROM T_DOC
WHERE CD_Message_ID = new.MSSG_ID;
The SET is not necessary.
I did make one other change that might make it work. I removed the space after CONCAT. Some versions of MySQL have trouble parsing spaces after function calls.

MySQL Remove part of string after specific character

I do got a database named "MAPPINGS" with about 23.000 rows I need to replace becouse of a mistake. Is there any query to achieve the following:.
UPDATE MAPPINGS SET MAIN = 'firt part' WHERE USERID = '1578' AND MAIN LIKE 'first part >%'
The problem is that "first part" is every time something else. I just need to remove everyhing after the ">" than the MAPPINGS are correct.
Or can this only be done by a PHP script? while select * from mappings where userid = '1578' and then the update query. I hope there will be a query to achieve this.
You can do this in MySQL using substring_index():
UPDATE MAPPINGS
SET MAIN = SUBSTRING_INDEX(MAIN, '>', 1)
WHERE MAIN LIKE '%>%' AND USERID = '1578';

Rails - update directly in SQL

Delving into the documentation and the api, I seem to be missing how to update one field in multiple rows at once.
Something like
Table.select(:field).update("update to this").where(id: 4,5,6)
would be nice.
Does something like this exist? It would be much better than having to store everything in an array, set it to a value, and calling save every time.
You can use the update_all method, for example:
Table.update_all("field = 'update to this'", ["id in (?)", ids])

Duplicate column and add an automatic extension with mySQL. How?

I have two columns with mySQL:
"part_no"
"pdf_link"
I need the "pdf_link" column to automatically grab/duplicate the "part_no" value and add a .pdf extension on the end.
For example: If part_no = 00-12345-998, then pdf_link = 00-12345-998.pdf
I need this to happen every time I insert.
I appreciate the help.
Erik
you can achive this effect by using triggers I think.
http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html
CREATE TRIGGER ins_pdf AFTER INSERT ON MY_TABLE SET #pdf_link = concat(#part_no,'.pdf')
Why store this extra computed information in the database? You can do this in the query when you pull it out, or, if needed, you could make a view that does it only as-needed.
Example pseudo query (my brain hurts right now, so this is only an example):
select concat(`part_no`, ".pdf") as `pdf_link` from `parts`;
If you really need this, you could use a trigger to duplicate the data ans add the extra string.