I'm trying to perform a check to see if a record exist first before inserting the record so I won't get an error.
If it exists, i'll update a field.
mydb(mydb.myitems.itemNumber==int(row)).update(oldImageName=fileName) or
mydb.myitems.insert(itemNumber=int(row),oldImageName=fileName)
If i try to update a record that does not exist, then it should throw a 1 or something aside from 0. But in the case above, it always throws a 0 so the insert keeps happening.
Why is that?
Thanks!
UPDATE:
Adding model:
mydb.define_table('myitems',
Field('itemNumber', 'id',notnull=True,unique=True),
Field('oldImageName', 'string')
If i try to update a record that does not exist, then it should throw a 1 or something aside from 0.
If you try to update a record that does not exist, .update() will return None, so the insert will then happen. If matching records exist, .update() will return the number of records updated.
In any case, you should instead do:
mydb.myitems.update_or_insert(mydb.myitems.itemNumber == int(row),
oldImageName=filename)
or alternatively:
mydb.myitems.update_or_insert(dict(itemNumber == int(row)),
oldImageName=filename)
The first argument to update_or_insert is _key, which can either be a DAL query or a dictionary with field names as keys.
This is basically a correction of Anthony's answer which did not give quite the desired result when I tried it. If you do:
mydb.myitems.update_or_insert(mydb.myitems.itemNumber == int(row),
itemNumber = int(row),
oldImageName=filename)
then the code should insert a record with the itemNumber and filename if there is not an item with that number there already, otherwise update it.
If you miss the itemNumber = int(row), bit then web2py makes up an itemNumber which is probably not what is wanted.
See http://www.web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#update_or_insert
Related
I'm doing an update query with PDO. I would like to figure out if my update query did not change anything in the database, since:
the passed values are the same as already present in the database. I know that rowCount() in such a case returns 0.
the row I'm trying to update does not exist in the database. As far as I can see, rowCount()in such cases also returns 0.
Am I forced to precede my UPDATE by a SELECT statement, to figure out if the record I'm trying to update does in fact exist? Or is there another common practice for this sort of thing.
I've been perusing through the documentation, but cannot find a conclusive answer:
http://php.net/manual/en/pdostatement.rowcount.php
I've come across this StackOverflow answer, that suggests that rowCount() might return NULL in some scenario's, but I don't think it's apliccable to my scenario:
see Why does PDO rowCount() return 0 after UPDATE a table without modifying the existing data?
From the comments in this question:
If the data hasn't been modified, the rowCount will be zero. If the
data was modified, the rowCount will be one or higher. If there was an
error, rowCount will be null or false or something non-zero.
UPDATE
I've found another question that gives an example of the proposition in the comments below:
Getting the insert and update ID with PDO
UPDATE2
Another question proposes another solution, via PDO::MYSQL_ATTR_FOUND_ROWS
PDO - check if row was updated?
You could add conditionals to your 'where' clause so such as " and ColumnToUpdate <> 'NewValue'"
I've solved it using the suggestions of #hjpotter92.
// UID is the unique ID of my table, autoincremented etc...
// Firstly, let's try to update my row
$query = 'UPDATE my_table SET x=0, y=1, uid=LAST_INSERT_ID(uid) WHERE z=2';
$sth = $dbh->prepare($query);
if($sth->execute()) {
if($dbh->lastInsertId() == 0) { // Record was not found, so insert it.
$query = 'INSERT INTO my_table (x,y) VALUES (0,1)';
$sth = $dbh->prepare($query);
$sth->execute();
if($sth->rowCount() > 0) {
echo $dbh->lastInsertId(); // Return the UID of the inserted row
}
}
}
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"});
I need to get last record from db. I'm using sqlalchemy.
At the moment, I'm doing like that:
obj = ObjectRes.query.all()
return str(obj[-1].id)
But it's too heavy query. How can I get last record better?
Take a look at Query.first(). If you specify a sort on the right column, the first will be your last. An example could look like this:
obj = session.query(ObjectRes).order_by(ObjectRes.id.desc()).first()
Sometimes it is difficult to reformulate simple things:
SELECT * FROM ObjectRes WHERE id IN (SELECT MAX(id) FROM ObjectRes)
but this worked for me:
session.query(ObjectRes).filter(ObjectRes.id == session.query(func.max(ObjectRes.id)))
Don't forget to disable existing ordering if needed
In my case I have dynamic ordered relationships:
class Match:
...
records = relationship("Record", backref="match", lazy="dynamic", order_by="Record.id")
And when I tried accepted answer I got first record, not the last, cause ORDER BY were applied twice and spoiled the results.
According to documentation:
All existing ORDER BY settings can be suppressed by passing None
So the solution will be:
match = db_session.query(Match).first()
last_record = match.records.order_by(None).order_by(Record.id.desc()).first()
This answer modifies the others to allow for cases where you don't know what the primary key is called.
from sqlalchemy.inspection import inspect
# ...
def last_row(Table: type, *, session): # -> Table
primary_key = inspect(Table).primary_key[0].name # must be an arithmetic type
primary_key_row = getattr(Table, primary_key)
# get first, sorted by negative ID (primary key)
return session.query(Table).order_by(-primary_key_row).first()
I have a Problem with MySQL update. The code below is working but i want to block that others try to enter Data at Field "status" again.
How can i write the command for that?
if(isset($_GET['up']))
{
if(strlen($_GET['up'])==71)
{
db_conn();
$raw = explode(":",$_GET['up']);
$sql = "UPDATE ".$database_table." SET status='".$raw[1]."',upl_time='".time()."' WHERE hash='".$raw[0]."' LIMIT 1";
if(mysql_query($sql))
{
print "ACK";
}
else
print "NACK";
}
exit;
}
There are a couple of ways to do so:
Add a field - IS_UPDATED - to your table to maintain some sort of a flag that defaults to FALSE. Then in your query that updates the status field, also set IS_UPDATED to TRUE. Also, in the update query, add this condition to the where clause - IS_UPDATED = FALSE. This will mean that the status column will only update if it has not already been updated.
If the field upl_time is originally NULL or empty, and is only updated in the above query, when the status column is updated, I think you can as well use this column instead of adding a new one. But this is better known by you.
I'm not sure what's the origin of the update query from your application. But if possible, you might also consider adding logic to your application to disable the UPDATE altogether.
I'd prefer approach 1.
I'm writing an application and I'm using MySQL as DBMS, we are downloading property offers and there were some performance issues. The old architecture looked like this:
A property is updated. If the number of affected rows is not 1, then the update is not considered successful, elseway the update query solves our problem.
If the update was not successful, and the number of affected rows is more than 1, we have duplicates and we delete all of them. After we deleted duplicates if needed if the update was not successful, an insert happens. This architecture was working well, but there were some speed issues, because properties are deleted if they were not updated for 15 days.
Theoretically the main problem is deleting properties, because some properties are alive for months and the indexes are very far from each other (we are talking about 500, 000+ properties).
Our host told me to use replace into instead of deleting properties and all deprecated properties should be considered as DEAD. I've done this, but problems started to occur because of syntax error and I couldn't find anywhere an example of replace into with a where clause (I'd like to replace a DEAD property with the new property instead of deleting the old property and insert a new to assure optimization). My query looked like this:
replace into table_name(column1, ..., columnn) values(value1, ..., valuen) where ID = idValue
Of course, I've calculated idValue and handled everything but I had a syntax error. I would like to know if I'm wrong and there is a where clause for replace into.
I've found an alternative solution, which is even better than replace into (using simply an update query) because deletes are happening behind the curtains if I use replace into, but I would like to know if I'm wrong when I say that replace into doesn't have a where clause. For more reference, see this link:
http://dev.mysql.com/doc/refman/5.0/en/replace.html
Thank you for your answers in advance,
Lajos Árpád
I can see that you have solved your problem, but to answer your original question:
REPLACE INTO does not have a WHERE clause.
The REPLACE INTO syntax works exactly like INSERT INTO except that any old rows with the same primary or unique key is automaticly deleted before the new row is inserted.
This means that instead of a WHERE clause, you should add the primary key to the values beeing replaced to limit your update.
REPLACE INTO myTable (
myPrimaryKey,
myColumn1,
myColumn2
) VALUES (
100,
'value1',
'value2'
);
...will provide the same result as...
UPDATE myTable
SET myColumn1 = 'value1', myColumn2 = 'value2'
WHERE myPrimaryKey = 100;
...or more exactly:
DELETE FROM myTable WHERE myPrimaryKey = 100;
INSERT INTO myTable(
myPrimaryKey,
myColumn1,
myColumn2
) VALUES (
100,
'value1',
'value2'
);
In your documentation link, they show three alternate forms of the replace command. Even though elided, the only one that can accept a where clause is the third form with the trailing select.
replace seems like overkill relative to update if I am understanding your task properly.