Rails Active Record: SQL Expression In Update Statement - sql

How can you execute the following SQL statement using AR:
UPDATE accounts SET balance = balance + 100 WHERE id = 1
I tried to find ways to execute SQL expressions in AR update statements, but nothing is working. I can not do something like
account.update balance: account.balance + 100
Because that would open all sort of race condition issues. The DBMS is the proper entity to handle this kind of update.
Any idea how to write it using AR?
I realize this can be done using:
Account.where(id: 1).update_all("balance = balance + 100")
But this looks very un-rails like to me. I was hoping for a cleaner solution

You need to do:
account.increment :balance, 100
increment is the documentation.

Related

Update date within a table, Postgresql

So I'm having trouble understanding on how to change the date on an update in postgres. What I have currently, that is giving a syntax error is
UPDATE works_locations SET (wrl_startdate = '2014-09-07', wrl_enddate = '2015-02-06')
with a few statements determining which field I should specifically change. However, postgres is giving me an error. How do I successfully change the date in postgres, even if the start date is around two years prior to this entry?
I don't have Postgres installed so I can't test this but try removing the parenthesis on your SET clause so that it looks like this:
UPDATE works_locations SET wrl_startdate = '2014-09-07', wrl_enddate = '2015-02-06'

Hibernate createSQLQuery and Toad SQL query return different results - parameter problems?

I'm a newbie at Hibernate so excuse me if some of this is glaringly obvious but it's been a very, very long day. I am trying to create and execute a simple query in Hibernate and Toad/Oracle.
The Toad/Oracle sql reads:
select
count(*)
from
fpps_owner.fee_claim_payment_lines l,
fpps_owner.fee_claim_payments p
where
l.fee_claim_payment_id = p.fee_claim_payment_id and
p.claim_index = 87167895
The above returns 10 records, which is correct
The following Java code returns 0 records, which is NOT correct
String sLinesAvailable =
"select count(*) from " +
"fpps_owner.fee_claim_payment_lines l, fpps_owner.fee_claim_payments p " +
"where " +
"l.fee_claim_payment_id = p.fee_claim_payment_id and p.claim_index = :id";
Query qLinesAvailable = em.createNativeQuery(sLinesAvailable);
qLinesAvailable.setParameter("id", "87167895"); // fails
qLinesAvailable.setParameter("id", 87167895); // fails
List<Object> out = (List<Object>) qLinesAvailable.getResultList();
BigDecimal x = (BigDecimal) out.get(0);
Returns 0 records. Using .getSingleResult() also returns 0 records.
What am I missing here?
Any help would be GREATLY appreciated!
If you are not seeing any malformed query errors, it seems like the parameter is not binding correctly.
To debug, I'd print out that SQL statement the line after you set the parameter. This is the only way you can see the SQL after the parameter is set in order to compare it with Toad.
What does your binding file look like? Maybe you have a different name in there for the ID, so it's not able to find it based on the name. Trying binding with the parameter's order value, just as a test.
This might give some ideas: http://www.mkyong.com/hibernate/hibernate-parameter-binding-examples/
Best of luck! We've all been there :)
What happens when you try:
(Number) query.getSingleResult();
Your query isn't returning a list, but rather just a count.
Good luck.

Yii Framework: How to get the num_rows?

As the official documentation does not say how to do a simply "num_rows" with their system, i need some help here: How to get the amount of rows in the result set ?
Assuming:
$connection=Yii::app()->db;
$command=$connection->createCommand($sql);
This will work for insert, update and delete:
$rowCount=$command->execute();
execute(): performs a non-query SQL statement, such as INSERT, UPDATE and DELETE. If successful, it returns the number of rows that are affected by the execution.
For select, you could do the following:
$dataReader=$command->query();
This generates the CDbDataReader instance and CDbDataReader provides a rowCount property
http://www.yiiframework.com/doc/api/1.1/CDbDataReader#rowCount-detail
$rowCount = $dataReader->rowCount;
About rowCount => Returns the number of rows in the result set. Note, most DBMS may not give a meaningful count. In this case, use "SELECT COUNT(*) FROM tableName" to obtain the number of rows.
ActiveRecord has count method which can be used.
$cntCriteria = new CDbCriteria();
$cntCriteria->condition = "categoryId = :categoryId";
$cntCriteria->params[':categoryId'] = $categoryRow->categoryId;
$articleCount = Article::model()->count($cntCriteria);
There is one more way to do this. When we execute a sql query it will return the result as array only. So we can able get the count of the rows using count() function like below.
$output=User::model()->findAllBySql("select * from user");//User is a model belongs to the user table
$count_val=count($output);//$count_val has the value of number of rows in the output.

SQL Update on joined tables with calculated fields

First of all, I know there are already questions and answers about it, this thread being the one that is closest to what I need:
SQL Update to the SUM of its joined values
However, I get a syntax error (operator missing) that seems to occur close to the FROM clause. However I can't see it. Does it not like the FROM itself ? I am not used to using FROM in an update statement but it seems like it's valid from the QA I just linked :|
Any idea why there would be a syntax error there ?
I am using Access 2007 SP3.
Edit:
Wow, I forgot to post the query...
UPDATE r
SET
r.tempsmoy_requete_min = tmm.moy_mob_requete
FROM
rapports AS r INNER JOIN
(SELECT
id_fichier,
Round(Sum(temps_requete_min)/3,0) As moy_mob_requete,
Round(Sum(temps_analyse_min)/3,0) As moy_mob_analyse,
Round(Sum(temps_maj_min)/3,0) As moy_mob_maj,
Round(Sum(temps_rap_min)/3,0) As moy_mob_rap,
Round(Sum(temps_ddc_min)/3,0) As moy_mob_ddc
FROM maintenances
WHERE
periode In (10,9,8) And
annee=2011
GROUP BY id_fichier) AS tmm ON rapports.id_rapport = tmm.id_fichier
WHERE
1=0
The WHERE 1=0 part is because I want to test further the subquery before running it.
Edit: This is some simpler query I am trying. I get a different error this time. It now tells me that tempsmoy_requete_min (and probably all other left operands) are not part of an aggregate function... which is the point of my query. Any idea ?
UPDATE
rapports INNER JOIN maintenances ON rapports.id_rapport = maintenances.id_fichier
SET
rapports.tempsmoy_requete_min = Round(Sum(temps_requete_min)/3,0),
rapports.tempsmoy_analyse_min = Round(Sum(temps_analyse_min)/3,0),
rapports.tempsmoy_maj_min = Round(Sum(temps_maj_min)/3,0),
rapports.tempsmoy_rap_min = Round(Sum(temps_rap_min)/3,0),
rapports.tempsmoy_ddc_min = Round(Sum(temps_ddc_min)/3,0)
WHERE
maintenances.periode In (10,9,8) And
maintenances.annee=2011 AND
1=0
I tried adapting your first query sample, and was able to make your error go away. However then I encountered a different error ('Operation must use an updateable query').
It may be possible to overcome that error, too. However, I found it easier to use a domain function instead of a join to retrieve the replacement value.
UPDATE rapports
SET tempsmoy_requete_min = Round(DSum("temps_requete_min",
"maintenances",
"periode In (10,9,8) AND annee=2011 "
& "AND id_fichier='" & id_rapport
& "'")/3, 0);
If this suggestion works for tempsmoy_requete_min with your data, you will have to extend it to the other fields you want to replace. That won't be pretty. You could make it less ugly with a saved query which you then use as the "Domain" parameter for DSum() ... that could allow you to use a simpler "Criteria" parameter.
UPDATE r
should be
UPDATE rapports
You can't reliably use an alias in the update target.

My simple sql update query is not working right :(

I've got a simple sql query that is trying to update a single row. The code came from some Linq-to-sql code (i used Profiler to grab it), but please don't worry about the source (L2S) ... that's irrelivant to the question.
Now, when i try and do an update with the where clause, I get 0 rows updated.
I then try and do a select with the same where clause. i get a single result back. Ok, so the data is there.
It's only when i turn off some of the where clause statements does the query finally work. I just don't get it :(
I can't really explain it. So I made a video showing this.
Please watch the video on YouTube here.
Can anyone help? It's really weird :(
Database is MS-SQL 2008.
-- UPDATE
The sql i'm trying to execute (after i've cleaned it up from L2S)..
update tblBoardPost
set IsSticky = 1
where IdBoardPost = 1278
and IdAddress = 212787
and Subject = N'ttreterte'
and Banner is null
and UniqueSubject = N'ttreterte5'
AND (NOT ([IsAnnouncement] = 1))
AND (NOT ([IsSticky] = 1))
AND (NOT ([IsLocked] = 1))
and IsVisible = 1
and IdUserModified = 1
AND [IdNewsArticle] IS NULL
AND [IdList] IS NULL
(note: yes, i know the NOT (blah = 1)) is weird, but that's L2S that made that.
Update 2:
The code in the video is being ran in a transaction/rollback trans. this means that if i do run one of those weird scenario's that works, the change works .. but the rollback undoes it .. so when i run it a 2nd time .. the original value has been returned to the db row.
Also, in the vid, the select query is not exactly the same as the update query .. because i've been trying so many permutations (with no luck) .. so by the time i made the vid .. i forgot to show the original code. That said, the same code in both the select statement and the update/where statement (when i copy/paste on my machine) reproduces the exact same probs :(
Update 2 :)
As per Lieven's request, here's the screenshot showing the code and then the results.
alt text http://img196.imageshack.us/img196/7111/lieven.png
I checked your video, and you should try the same SQL conditions, that you used to return one row in your select query, in your update query. The conditions in the two SQL statements in your video aren't the same, and I don't really care why; they're not apples to apples.
Just copy and paste the working WHERE clause over the non-working one.
In the video, your select goes like
and not IsAnnouncement = 1
wich gives entirely different results as in your update
and not (IsAnnouncement = 1)
It seems you are suffering from an operator precedence issue .
Edit
as the queries don't match in your video and although you say they have matched could you copy paste following script and let us know if or if they do not give you the same results? (I for one would have a hard time believing that the rows affected would differ)
begin tran
select *
from tblBoardPost
where
IdBoardPost = 1278
and IdAddress = 212787
and Subject = N'ttreterte'
and Banner is null
and UniqueSubject = N'ttreterte5'
AND (NOT ([IsAnnouncement] = 1))
AND (NOT ([IsSticky] = 1))
AND (NOT ([IsLocked] = 1))
and IsVisible = 1
and IdUserModified = 1
AND [IdNewsArticle] IS NULL
AND [IdList] IS NULL
update tblBoardPost
set IsSticky = 1
where
IdBoardPost = 1278
and IdAddress = 212787
and Subject = N'ttreterte'
and Banner is null
and UniqueSubject = N'ttreterte5'
AND (NOT ([IsAnnouncement] = 1))
AND (NOT ([IsSticky] = 1))
AND (NOT ([IsLocked] = 1))
and IsVisible = 1
and IdUserModified = 1
AND [IdNewsArticle] IS NULL
AND [IdList] IS NULL
rollback tran