How to declare a variable within the same statement in MySQL? - mysql

How do I create variables in MySQL that I can refer to in the same statement?
Does this work for UPDATE and INSERT statements as well?
I asked this because I got a lot of SQL text files where I execute single commands using Ctrl-Enter from MySQL-Workbench. If it would be multiple statements I would have to select the commands to execute before pressing Ctrl-Enter. This is more complex and error-prone.
Before someone asks: this is a private database with single user and I use these scripts to modify data directly where editing through the GUI would take ages.
I just decided that I should wrap more complex code with a java program. This was a good decision. Still I need the solution to this question for less complex problems where I don't want to write java code.

It's not clear why you need to do this in the same statement. It's easy to run two statements, and it makes the code much easier to write and easier to understand. You should always consider how the developer who succeeds you working on your code is going to understand and maintain it.
SET #variable = 'Value';
SELECT ... FROM your_table WHERE a_column = #variable;
If you do need to do it in one statement, I'd do it this way:
SELECT ... FROM your_table
CROSS JOIN (SELECT #variable := 'Value') AS _init
WHERE a_column = #variable;
By doing this in a derived-table, it only does the assignment once. If you do it in the select-list as you showed in your solution, it does the assignment as many times as the number of rows returned by the inner query. This is not a big deal if the assignment is for a constant value, but if your variable is assigned the result of a costly expression, it will be slow.

Well I wasn't able to find a solution on the web. But it turned out to be... fairly straightforward.
Just create a statement that wraps your statement:
select *, #variable:='Value' from (
select * from your_table inner where #variable=inner.column
) as outer

Related

Disable MySQL's UNION SELECT query

Is it possible to completely disable UNION SELECT queries thru a configuration option?
Besides cleaning the entry params, I would like to avoid the use of UNION since with its help it is pretty easy to implement SQL injection of the form:
SELECT * FROM users where username = '1' OR 1=1
UNION
SELECT * FROM users -- ' AND password='something'
To answer your question plainly:
No, there is no option in MySQL to selectively disable UNION.
SQL_MODE can be used to change the meaning of syntax in a couple of very specific cases, like use of double-quotes and the || operator. See https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
But in general, you cannot disable SQL keywords or clauses, unless you whip out your code editor and modify MySQL's SQL parser code, and then build a custom instance of MySQL.
I agree with the other commenters that it isn't necessary to disable UNION if you write application code with the known practices to avoid SQL injection vulnerabilities.
Even it's easy to do SI with plain SELECT query as well and it has nothing to do with UNION at all. Moreover, as far I know, NO there is no such option to disable UNION unless you are probably taken the open source code and modified it yourself.
The best [proven] solution to avoid SQL Injection is to avoid assembling SQL statements by concatenating strings with values coming from the end user interface (or other unsafe source).
It's safer to use "Prepared Statements" and apply parameters to it, instead of concatenating those parameters.
There's still room for concatenating SQL chunks into a statements, primarily when using Dynamic SQL, but I think this is out of the scope of your question. In simple words: do not concatenate values as strings when producing a SQL statement.

flow control in MYSQL

I am trying to convert a SQL Server query to MYSQL, but am having trouble with the IF statements. In the SQL Server version, they are used to direct the flow of the query based on a flag, but I cannot get it to work in MYSQL. I have outlined how the code works below:
The script sets a flag based upon how much data can be matched between the query and the database.
It then performs a select statement based upon the flag: if flag=1 select a,b,c where match logic
else if flag=2 select d,e,f where different match logic
I have tried using both IF and CASE WHEN, neither of which work. I would normally have put the IF within the WHERE clause, but different columns are selected depending upon the flag.
Is there a function that will perform IF/ELSE flows MYSQL?
Any help would be greatly appreciated!
Assuming the types and number of columns are compatible, you could do:
select a, b, c
from t
where (v_flag = 1) and match_condition_1
union all
select d, e, f
from t
where (v_flag = 2) and match_condition_2;
The alternative is to use a stored procedure. In MySQL, the if control flow statement is only allowed in programming blocks -- stored procedures, stored functions, and trigger.

Is it possible to do a JOIN without knowing ON what column the JOIN is done?

Is there, for example, a function such as SELECT t0.*, t1.* JOIN t1 ON t0.some_known_field = GET_PRIMARY_INDEX(t1)?
No, it is not possible, in pure SQL, to use any sort of variable or lookup to construct the names of tables or columns.
You can use "dynamic SQL" which is a fancy-sounding way of having a stored procedure construct a text string from queries and other information and then run it as a SQL statement. Or you can do the same in your application program. Many SQL applications do this sort of thing.

Inline table-valued function vs Stored Procedure (SQL Server)

I'm a bit confused about what is better to use in the following case:
I have a quite complex query that is used for reporting purposes. A simplified version looks like
SELECT [type], COUNT(*) as total_num, COUNT(DISTINCT user_id) as uq_user_num
FROM table1
INNER JOIN table2 ON (...)
...
WHERE table3.last_action_date BETWEEN :start_date AND :end_date
GROUP BY [type]
I can create an inline function or a stored procedure that takes start_date and end_parameters and executes this query.
I incline to function because this task does not involve any data modification or complex logic. Also, I may want to use the result in APPLY later (it's not really important at the moment).
Does it make sense to use function, not procedure? Is it any difference from performance point of view (execution plan caching, etc) ?
Thank you.
Using a multi-statement table valued function is similar to using a proc from plan caching and cached plan reuse perspective.. Using an inline table valued function is similar to using a view from the plan cache and plan reuse perspective(reuse only happen is exact same statement is used. ie same parameters).
Considering the same you should use a multi-statement table valued function.
You may want to consider using a View too. A view is efficient if the results do no change given the parameters provided, which is what you have here. In this case, the results will not change if you make two calls with the same start and end date.
However, two of the main differences between a stored proc and a function are that you cannot call updates/ inserts from a function and you cannot call a stored proc as part of a select statement, but you can with a function.
See this thread for more info:
Function vs. Stored Procedure in SQL Server

Saving commands for later re-use in MySQL?

What would be the equivalant in MySQL for:
Saving a command for later reuse.
eg: alias command1='select count(*) from sometable;'
Where then I simply type command 1 to get the count for SomeTable.
Saving just a string, or rather part of a command.
eg: select * from sometable where $complex_where_logic$ order by attr1 desc;
WHere $complex_where_logic$ is something I wish to save and not have to keep writing out
Another approach is to create a view with your $complex_where_logic$ and query the view instead of the tables:
CREATE VIEW my_view AS SELECT * FROM sometable WHERE $complex_where_logic$
SELECT my_column FROM my_view ORDER BY some_column
Whenever you query a view, you always get the up-to-date data. Internally, MySQL runs the SELECT given in the CREATE VIEW statement and queries the results in order to obtain the results of your current SELECT. Therefore, a view does not improve performance compared to a single query. There a two main advantages in using views:
you have simpler SELECT statements since you do not have to type complex WHERE or JOIN Syntax again and again
you can use it to control user privileges, e.g. give a user access to a view but not to the original tables; this is not useful in your example, but - for example - you can think of views containing aggregate data only
This "template" feature could be part of client tools. Basically I use Toad. It has record macros feature. I think it is possible to do.
I take it the answer you are looking for isn't 'stored procedures'...?
I found that the best solution for this is just any rich GUI for SQL queries (TOAD, mysql query browser, etc). They offer the ability to save commands and browse them and well, of course, much more.