Update statement followed by select MySQL - mysql

I am storing cache information from the cache server if application version is matching else I need to set cache details as NULL.
Currently I am doing it like this
UPDATE
cache_table
SET
_data = NULL
WHERE _id = id AND _app_version != "current_version"
Followed by select query
SELECT
_data
FROM
cache_table
WHERE _id = id AND _app_version == "current_version"
Is there a way I can do required update and select in one query without firing two query ?
Note: I don't want to use MySQL procedure. No specific reason but don't want to store application logic in DB so I can easily change database application.

Generally UPDATE and SELECT are two distinct operations. The only way to combine them is with a stored procedure as you identify.

I dont believe in MySQL there is a built-in way to do this. However, just FYI this can be done in SQL Server using OUTPUT clause:
http://msdn.microsoft.com/en-us/library/ms177564.aspx

Related

mysql) select values if table exists

I'm trying select all values if such table exists. If it doesn't exist, just leave it.
I'm trying to do this only in one MYSQL code. Not with the help of python or something.
SELECT CASE WHEN (SELECT count(*)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '{db0}' AND TABLE_NAME = '{table0}')=0
THEN 'None' ELSE (SELECT MAX({colname}) FROM {db0}.{table0}) END;
If i inject existing table name on it, it works well.
But if not , it shows the error sign that saying such table doesn't exist.(Table 'corps.060311' doesn't exist)
What should I do?
This cannot be achieved using a simple query because MySQL analyses the query as a whole before performing it: it is not a procedural language and the queries are never executed line by line.
To do what you want to do without help of any other language, you must use stored procedures: https://dev.mysql.com/doc/refman/8.0/en/create-procedure.html
So the first step is to add a new FUNCTION in your database that will contain the "if table exists" part (see https://dev.mysql.com/doc/refman/8.0/en/if.html for if statements) and will return the desired value based on the schema, table, and column provided as strings in input of the function.
Then you can use the FUNCTION in any query in your database.

Can't specify target table for update in FROM clause - Mysql 5.7.10 - derived_merge not working

I have the following query:
update tblwerknemerdienst toUpdate
set datumtot = (select subdate(datumvanaf,1)
from (select * from tblwerknemerdienst) nextDienst
where nextDienst.Werknemer = toUpdate.Werknemer
and nextDienst.datumvanaf > toUpdate.DatumVanaf
order by DatumVanaf
LIMIT 1)
WHERE DatumTot IS NULL;
The query runs fine on MySql versions other than MySql 5.7.10. I've searched around the web and found that you have to set derived_merge=off, but sadly this had no effect and the query still fails with the same error.
I have also tried several different ways of rewriting the query, but all to no avail.
Is there something I'm missing or is there another way to accomplish this?
In the end I fixed this by rewriting the whole thing in a procedure, where I used a cursor to execute the query and get the necessary data. Then I perform the update statement based upon the fields selected in the cursor.
This seemed to be the only way to reliably perform the operation required on different versions of MySql.

Can I INSERT/UPDATE into two tables with one query?

Here is a chunk of the SQL I'm using for a Perl-based web application. I have a number of requests and each has a number of accessions, and each has a status. This chunk of code is there to update the table for every accession_analysis that shares all these fields for each accession in a request.
UPDATE accession_analysis
SET analysis_id = ? ,
reference_id = ? ,
status = ? ,
extra_parameters = ?
WHERE analysis_id = ?
AND reference_id = ?
AND status = ?
AND extra_parameters = ?
and accession_id is (
SELECT accesion_id
FROM accessions
where request_id = ?
)
I have changed the tables so that there's a status table for accession_analysis, so when I update, I update both accession_analysis and accession_analysis_status, which has status, status_text and the id of the accession_analysis, which is a not null auto_increment variable.
I have no strong idea about how to modify this code to allow this. My first pass grabbed all the accessions and looped through them, then filtered for all the fields, then updated. I didn't like that because I had many connections with short SQL commands, which I understood to be bad, but I can't help but think the only way to really do this is to go back to the loop in Perl holding two simpler SQL statements.
Is there a way to do this in SQL that, with my relative SQL inexperience, I'm just not seeing?
The answer depends on which DBMS you're using. The easiest way is to create a trigger on one table that provides the logic of updating the other table. (For any DB newbies -- a trigger is procedural code attached to a table at the DBMS (not application) layer that runs in response to an insert, update or delete on the table.). A similar, slightly less desirable method is to put the logic in a stored procedure and execute that instead of the update statement you're now using.
If the DBMS you're using doesn't support either of these mechanisms, then there isn't a good way to do what you're after while guaranteeing transactional integrity. However if the problem you're solving can tolerate a timing difference in the two tables' updates (i.e. The data in one of the tables is only used at predetermined times, like reporting or some type of batched operation) you could write to one table (live) and create a separate process that runs when needed (later) to update the second table using data from the first table. The correctness of allowing data to be updated at different times becomes a large and immovable design assumption, however.
If this is mostly about connection speed, then one option you have is to write a stored procedure that handles the "double update or insert" transparently. See the manual for stored procedures:
http://dev.mysql.com/doc/refman/5.5/en/create-procedure.html
Otherwise, You probably cannot do it in one statement, see the MySQL INSERT syntax:
http://dev.mysql.com/doc/refman/5.5/en/insert.html
The UPDATE syntax allows for multi-table updates (not in combination with INSERT, though):
http://dev.mysql.com/doc/refman/5.5/en/update.html
Each table needs its own INSERT / UPDATE in the query.
In fact, even if you create a view by JOINing multiple tables, when you INSERT into the view, you can only INSERT with fields belonging to one of the tables at a time.
The modifications made by the INSERT statement cannot affect more than one of the base tables referenced in the FROM clause of the view. For example, an INSERT into a multitable view must use a column_list that references only columns from one base table. For more information about updatable views, see CREATE VIEW.
Inserting data into multiple tables through an sql view (MySQL)
INSERT (SQL Server)
Same is true of UPDATE
The modifications made by the UPDATE statement cannot affect more than one of the base tables referenced in the FROM clause of the view. For more information on updatable views, see CREATE VIEW.
However, you can have multiple INSERTs or UPDATEs per query or stored procedure.

MySQL to SQL Server select statement

I am converting mysql sprocs to SQL Server. I've come across a select statement in mysql that I don't quite understand what it's doing and my google-fu/so-fu has failed me. Here is the gist of it:
SELECT AccountType = dbo.functionToGetAccountType() FROM AccountLookup
I don't have the ability to debug the original mysql. I do know that the function only returns a single value.
Is the mysql statement assigning a default value to 'AccountType' in the event there are no rows in the AccountLookup table?
Thanks for your time.
The select statement is executing the function dbo.functionToGetAccountType() and aliasing the column as AccountType. It could be re-written as:
SELECT dbo.functionToGetAccountType() as AccountType
FROM AccountLookup

Can I launch a trigger on select statement in mysql?

I am trying to run an INSERT statement on table X each time I SELECT any record from table Y is there anyway that I can accomplish that using MySQL only?
Something like triggers?
Short answer is No. Triggers are triggered with INSERT, UPDATE or DELETE.
Possible solution for this. rather rare scenario:
First, write some stored procedures
that do the SELECTs you want on
table X.
Then, restrict all users to use only
these stored procedures and do not
allow them to directly use SELECT on table
X.
Then alter the stored procedures to
also call a stored procedure that
performs the action you want
(INSERT or whatever).
Nope - you can't trigger on SELECT - you'll have to create a stored procedure (or any other type of logging facility - like a log file or what ever) that you implicitly call on any query statement - easier if you create a wrapper that calls your query, calls the logging and returns query results.
If you're trying to use table X to log the order of SELECT queries on table Y (a fairly common query-logging setup), you can simply reverse the order of operations and run the INSERT query first, then run your SELECT query.
That way, you don't need to worry about linking the two statements with a TRIGGER: if your server crashes between the two statements then you already logged what you care about with your first statement, and whether the SELECT query runs or fails has no impact on the underlying database.
If you're not logging queries, perhaps you're trying to use table Y as a task queue -- the situation I was struggling with that lead me to this thread -- and you want whichever session queries Y first to lock all other sessions out of the rows returned so you can perform some operations on the results and insert the output into table X. In that case, simply add some logging capabilities to table Y.
For example, you could add an "owner" column to Y, then tack the WHERE part of your SELECT query onto an UPDATE statement, run it, and then modify your SELECT query to only show the results that were claimed by your UPDATE:
UPDATE Y SET owner = 'me' WHERE task = 'new' AND owner IS NULL;
SELECT foo FROM Y WHERE task = 'new' AND owner = 'me';
...do some work on foo, then...
INSERT INTO X (output) VALUES ('awesomeness');
Again, the key is to log first, then query.