how to configure the table at runtime in mysql query - mysql

people know that we can use if statement to configure a query in the select statement like this
select if(var=1,amount,amount/2) from mytable;
But what if I want to achieve something like this:
select amount from if(var=1,mytable1,mytable2);
Is there any way to configure the table at run time?

SELECT amount FROM mytable1 WHERE #var = 1
UNION
SELECT amount FROM mytable2 WHERE #var = 0
UPD: Here's what MySQL EXPLAIN looks like for the part of the query which has a condition evaluating to FALSE:
Note the Impossible WHERE part. MySQL recognizes that the expression in WHERE is constantly evaluating to FALSE, so it doesn't even try executing the query. Hence, no performance overhead when using this approach.

(Upgrading to an answer)
Where did var come from?
If it's a variable in another language, you could test it in that other language and then construct different SQL as appropriate:
$sql = "SELECT amount FROM " . ($var = 1 ? "mytable1" : "mytable2");
If it's a user variable in SQL, you could similarly use an IF statement around the two alternative SELECT statements:
DELIMITER ;;
IF #var = 1 THEN
SELECT amount FROM mytable1;
ELSE
SELECT amount FROM mytable2;
END IF;;
DELIMITER ;
If it's anything else (like a field from your tables), then your question doesn't make a great deal of sense.

Based on the mysql manual pages, it appears you cannot do this with the traditional syntax.
"User variables are intended to provide data values. They cannot be used directly in an SQL statement as an identifier or as part of an identifier, such as in contexts where a table or database name is expected, or as a reserved word such as SELECT."
- [http://dev.mysql.com/doc/refman/5.6/en/user-variables.html][1]
The exception to this is that you can assemble a prepared statement, but is probably not a better solution for most programming tasks. It would be better to leave the sql string generation to the language invoking mysql.
But, if you are doing this as part of a "sql only" task, like an import, this seems to be the approach you must take.
SET #s = CONCAT("SELECT * FROM ", if(true, "table1", "table2"), " LIMIT 1");
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #s = CONCAT("SELECT * FROM ", if(false, "table1", "table2"), " LIMIT 1");
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Related

MySQL - create a table with all of the fields that two tables have [duplicate]

I have to convert a MSSQL stored proc that passes a varchar that is a query:
INSERT INTO Results
EXEC (#Expresion);
This isn't working. I'm pretty sure that EXEC and EXECUTE aren't MySQL commands, but CALL doesn't work either.
Does anyone know if it's even possible to have something like JavaScript's eval function for MySQL?
I think you're looking for something like this:
SET #queryString = (
SELECT CONCAT('INSERT INTO user_group (`group_id`,`user_id`) VALUES ', www.vals) as res FROM (
SELECT GROUP_CONCAT(qwe.asd SEPARATOR ',') as vals FROM (
SELECT CONCAT('(59,', user_id, ')') as asd FROM access WHERE residency = 9
) as qwe
) as www
);
PREPARE stmt FROM #queryString;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #asd = NULL;
This is the SQL equivalent of eval(my_string);:
#Expression = 'SELECT "Hello, World!";';
PREPARE myquery FROM #Expression;
EXECUTE myquery;
Basically I combined the existing answers, neither tells you how to do eval exactly.
If you want to add parameters, you can use this:
#username = "test";
#password = "asdf";
#Expression = 'SELECT id FROM Users WHERE name = ? AND pass = ?;'
PREPARE myquery FROM #Expression;
EXECUTE myquery USING #username, #password;
And to answer the original question exactly:
#Expression = 'SELECT "Hello, World!";'
PREPARE myquery FROM #Expression;
INSERT INTO Results
EXECUTE myquery;
Note that the PREPARE ... FROM statement wants a session variable (prefixed with #). If you try to pass a normal variable, it will throw its hands up in the air and it just won't care.
EXECUTE is a valid command in MySQL. MySQL reference manual
The EXECUTE MySQL command can only be used for one prepared statement.
If case you want to execute multiple queries from the string, consider saving them into file and source it, e.g.
SET #query = 'SELECT 1; SELECT 2; SELECT 3;';
SELECT #query INTO OUTFILE '/tmp/temp.sql';
SOURCE /tmp/temp.sql;

How to set a local list/tuple variable in mysql

Is there a way to do the following in mysql?
SET #studios = ('Disney', 'Warner Bros.', 'Fox');
SELECT * FROM movies WHERE provider IN #studios;
When I try doing the above I get the error:
Operand should contain 1 column(s)
The error is coming from your initial assignment. You cannot assign lists to variables.
The only way of doing this in MySQL is to either create a temp table to hold the values, and then do ... IN (SELECT someVal FROM thatTemp), or to dynamically create the query with the values directly in the query string.
Example temp table creation:
CREATE TEMPORARY TABLE `someTemp` ( someVal VARCHAR(16) );
INSERT INTO `someTemp` (someVal) VALUES ('a'), ('b'), ('c');
SELECT * FROM myTable WHERE myField IN (SELECT someVal FROM someTemp);
DELETE TEMPORARY TABLE `someTemp`;
Alternatively, there is also FIND_IN_SET, which could be used like this:
SET #list = 'a,b,c';
SELECT * FROM myTable WHERE FIND_IN_SET(myField, #list) <> 0;
but this method probably has extremely poor performance (and may not be useable if your "myField" values may contain commas).
It is not possible to set a tuple/list/array in a user-defined variable in MySQL. You can use Dynamic SQL for the same:
-- we use single quotes two times to escape it
SET #studios = '(''Disney'', ''Warner Bros.'', ''Fox'')';
-- generate the query string
SET #query = CONCAT('SELECT * FROM movies WHERE provider IN ', #studios);
-- prepare the query
PREPARE stmt FROM #query;
-- execute it
EXECUTE stmt;
-- deallocate it
DEALLOCATE PREPARE stmt;
You could concatenate your list to a string, and use FIND_IN_SET as your criteria. Might not be super efficient, but makes the code quite easy to read and maintain.
Looks like this:
SET #studios = CONCAT_WS(',',
'Disney',
'Warner Bros.',
'Fox'
);
SELECT * FROM movies
WHERE FIND_IN_SET(provider, #studios) <> 0;

MYSQL - Prepared Statement NULL handling

I have good number of prepared statements in my MYSQL stored procedure . There is a chance the statement can become NULL ( the dynamically generated SQL statement ) , so to avoid run time exception I am using the below approach always . But since I am using prepared statements a lot , giving NULL check every where looks noisy .
SET #s10=CONCAT('UPDATE tlist SET total_count=total_count-1 WHERE group_id =',in_location_id,' AND sub_type=',COMPANY_COUNT,' AND sub_id in (',var_companies,')' );
IF(#s10 is NOT NULL) THEN
PREPARE stmt FROM #s10;
EXECUTE stmt;
END IF;
So is there any other approach that I can follow to mimize the above code into one or two lines ?
( Making statement and executing it together and Null handling together in one step ?)
I know I can run small subroutine and pass the prepared statement to it and do the above check , But want to know if there is any inbuilt MYSQL functionality for it .
Thank You
try
SET #s10=CONCAT('UPDATE tlist SET total_count=total_count-1 WHERE group_id =',in_location_id,'
AND sub_type=',COMPANY_COUNT,' AND sub_id in (',var_companies,')' );
IF(!ISNULL(#s10) && LENGTH(trim(#s10)) > 0) THEN
PREPARE stmt FROM #s10;
EXECUTE stmt;
END IF;

Set MySQL Column Alias to a Calculated Date

I'm looking to do something like this:
select data AS curdate() from table;
so the resulting table would look like:
2013-04-26
data 1
data 2
data 3
I can't figure out the syntax, but it must be possible?
I've tried it without quotes of any kind, which returns an error. Single quotes and back ticks both return the SQL itself as the column header.
That's an unusual requirement, but if you insist, you'd have to use dynamic sql.
SET #curdate = CURDATE();
SET #sql = CONCAT('SELECT whatever AS "', #curdate, '" FROM whatever');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
An alias is considered an identifier and cannot be assigned to a function without the use of dynamic SQL. It would break referencing such as:
SELECT *
FROM (SELECT 1 AS curdate()) a

convert mysql stored procedure to mssql

I need to used dynamic order query in mysql and i have successfully achieved that through string concatenation in mysql as follows:
set #stmt_text := concat('select * from abc order by ',sorder);
prepare stmt_handle from #stmt_text;
execute stmt_handle;
deallocate prepare stmt_handle;
i need a similar way to convert this in mssql
Any ideas??
Yes, just run it like this:
execute ('select * from abc order by ' + #sorder);
But don't forget that you need to verify the sorder variable if you get it through user input (to stop sql-injections)