I want to update some results in a table that would match a few conditions (i.e. variables from other tables to match a SELECT statement)
I've found something similar to this, on the net:
START TRANSACTION;
SELECT * FROM score_test,score_2,score_3, etc WHERE score=20000 AND score_test.id=score_2.id AND etc.. FOR UPDATE;
UPDATE score_test SET name='Test';
COMMIT;
NOTE: UPDATE score_test SET ... WHERE does not satisfy my needs as I need to gather the results that satisfy the SELECT statement
But it didn't work. It updates all my fields. What I am looking for is a syntax to use to UPDATE only the RESULTS from the SELECT statement.
My database is split into 10-15 tables and conditions may vary as I have to update some fields that STRICTLY accomplish some conditions that depend on the queries from other tables.
SQL UPDATE statements accept WHERE clauses just like SELECT statements do:
UPDATE score_test SET name='Test' WHERE score=20000;
edit
You can also treat the part following UPDATE as roughly the same as the part of a SELECT which follows FROM, which means you can do joins:
UPDATE score_test
JOIN test ON test.id=score_test.test_id
SET score_test.name = 'Test'
WHERE score_test.score=20000
The hints for this are in the UPDATE documentation, where it uses the table_reference symbol in the syntax definition. The syntax for table_reference is defined on the JOIN page. Implying identical treatment in both SELECT and UPDATE queries.
note on FOR UPDATE
the FOR UPDATE clause in a SELECT statement does not actually do anything related to updates... it only gathers a lock on the rows. You still need to follow that with an appropriate UPDATE query which does all the necessary JOINS and WHEREs (likely the same as your SELECT)
There are multiple ways to accomplish what you are asking. The simplest to just satisfy your question is to just do an update.
UPDATE score_test SET name='Test' WHERE score=20000;
If you want to satisfy conditions from multiple tables, you can use joins, just like a select statement, in the update statement.
You can further accomplish your goals, if you have such a complex use case, by creating a temporary table that holds the IDs of the items you want to edit, and cull that table one by one through multiple DELETE queries until you have the set you want to update.
Related
This might be a very stupid questions, but I am keen to know if anyone has any suggestions:
Single Table Delete Correct Query : delete from vehicle_owner where id=3;
Single Table Delete InCorrect Query : delete from vehicle_owner v where v.id=3
Mulitple Table Delete : delete v,s from vehicle v , category s where v.id=3 and v.id=s.id;
Qs 1: I was wondering that why 1st is right and why 2nd is incorrect. Basically I am looking for logical answers which explains why providing an alias in delete query is incorrect.
Qs 2: why we keep two alias names after 'DELETE' keyword for multiple delete. Anyways we are providing complete details in join condition. So why it is designed in such a way.
The second is incorrect because if you use an alias, the SQL statement is considered a version of the multi-table DELETE that just happens to have only one table specified. As such, it must follow the other rules of multi-table DELETE. There's no room in the syntax for single-table DELETE to specify an alias.
You don't need to have aliases, but you do need to specify which of the tables you are deleting from. So you list the tables, or their aliases, directly after the DELETE keyword. Otherwise, MySQL won't know whether to delete rows only from the first table (with the other tables being present to filter) or to delete from all tables, or some combination.
See: https://dev.mysql.com/doc/refman/5.5/en/delete.html
The full correct syntax for your second example would be:
delete v from vehicle_owner as v where v.id = 3
Once you've specified the alias, you need to also specify it in the delete clause.
For your second question, I'm not quite sure what you're asking.
I would like to query a database table for some of it's oldest entries and update them with a second query afterwards.
But how can I prevent that another process (that does the same) will return the same rows by the SELECT query and the UPDATE part will modify the entries twice?
As far as I see a simple transaction cannot prevent this from happening.
Use the SELECT ... FOR UPDATE mechanism to do this (see http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html)
I have a left join query that shows all the fields from a primary table (tblMarkers) and the values from a second table (tblLocations) where there is matching record.
tblLocations does not have a record for every id in tblMarkers
$query ="SELECT `tblMarkers`.*,`tblLocation`.*,`tblLocation`.`ID` AS `markerID`
FROM
`tblMarkers`
LEFT JOIN `tblLocation` ON `tblMarkers`.`ID` = `tblLocation`.`ID`
WHERE
`tblMarkers`.`ID` = $id";
I am comfortable with using UPDATE to update the tblMarkers fields but how do I update or INSERT a record into tblLocations if the record does not exist yet in tblLocations.
Also, how do I lock the record I ma working on to prevent someone else from doing an update at the same time?
Can I also use UPDATE tblMarkers * or do I have to list every field in the UPDATE statement?
Unfortunately you might have to implement some validation in your outside script. There is an IF statement in SQL, but I'm not sure if you can trigger different commands based on it's outcome.
Locking
In terms of locking, you have 2 options. for MyISAM tables, you can only lock the entire table using http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
LOCK TABLE users;
For InnoDB tables, there is no explicit 'lock' for single rows, however you can use transactions, to get exclusive rights during the operation. http://dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html
Update
There might be some shorthand notation, but I think you have to list every field in your query. Alternatively, you can always read the entire row, delete it and insert again using shorthand INSERT query. It all depends on how many fields you've got.
I make 2 queries in a transaction: SELECT (containing JOIN clause) and UPDATE. It is required that data in selected rows don't change before the update is done, so i'm using FOR UPDATE clause. My question is: does the 'for update' works only for part of data selected from table specified in FROM clause or for data from joined tables also? My DBMS is MySql.
The documentation simply says that the lock is on rows read without excepting joined tables, so it should be on all records on all the joined tables. If you want to lock only the rows in one of the tables, you can do that separately: 'SELECT 1 FROM keytable WHERE ... FOR UPDATE'.
That said, this is not needed to simply prevent an update between the SELECT and UPDATE. The read lock on the SELECT already does this. The purpose of the FOR UPDATE would be to prevent another transaction from reading the rows and thus potentially causing a deadlock because the UPDATE can not be applied until the other transaction releases its read lock.
Does anyone know what would be more efficient and use less resources:
Method 1-- Using a single SELECT statement to get data from one table and then iterating through it to execute multiple UPDATEs on another table. E.G. (pseudo-code, execute() runs query):
Query1_resultset = execute("SELECT item_id, sum(views) as view_count FROM tableA WHERE condition=1");
while(Query1_resultset as row) {
execute("UPDATE tableB SET view_count=row.view_count WHERE id=row.item_id");
}
Method 2-- Use a single INSERT.. ON DUPLICATE KEY UPDATE statement with a nested SELECT statement. E.G.:
INSERT INTO tableB (id, view_count) SELECT item_id, SUM(views) as view_count FROM tableA WHERE condition=1 ON DUPLICATE KEY UPDATE view_count=VALUES(view_count);
Note: ID on tableB is a primary key. There actually won't be any INSERTS because I know the key will exist. So it's all UPDATEs. Just using this statement to pass in a single query rather than multiple.
I'm really curious as to why either would be more efficient. Is it the number of queries that determines how quickly it will run? Where is the bottleneck?
I'm looking for something that will scale (the number of rows being updated grows daily).
Any ideas?
Thanks
It depens on your update/insert ratio. If you have lots of inserts and only a couple of updates than the INSERT ... ON DUPLICATE KEY UPDATE statement will be faster.
If you mainly have updates, than you would be better off with an UPDATE statement and an insert as fallback (if there was no update). You could use the multi table update clause to do it with a single update instead of a select followed by an update by the way. If you're doing both a SELECT and an UPDATE than the INSERT will definately be faster.
I think INSERT.. ON DUPLICATE KEY UPDATE is more efficient (otherwise, it wouldn't make much sense to add such an extension). By the way, your first example is not exactly the same as the second one - you neither use transactions nor you lock the table, so it's possible that the record returned by SELECT will not exist by the time you execute UPDATE.