How to dynamically set value in mysql query from an object? - mysql

I am trying to have an abstract method that can handle any update to a particular table. I want this to pull and set dynamically without using any additional code logic.
I know of a few ways to accomplish this, either using addition code logic or just refining the query to be more explicit.
let result = await db.query(`UPDATE media SET ? WHERE product_id=?;`, [[data.variant_id], productId]);
return result;
}
I would like to have the set value be, in this case, variant_id=.
I don't know of a way to accomplish this in the query itself other than setting the value prior to the query

You missed the column name
let result = await db.query('UPDATE media SET your_column_name = ?
WHERE product_id=?;',
[[data.variant_id], productId]);
and don't use backtics for sql string use single quote instead .. In mysql backtics are used for composite column name and column name containing reserved word

Use the prepare statement for Mysql dynamic update fields
set #stmt = concat ("UPDATE media SET variant_id=",data," WHERE product_id=",productId," ;");
prepare resultset from #stmt;
execute resultset;
deallocate prepare resultset;

Related

Changing Dynamic Table name in Query based on week number [duplicate]

I want to use variable in table name position like:
SELECT * FROM #targetTableName
However it makes error.
Is there any way to use variables in table name place in MySQL?
There are two reasons the query you show doesn't work.
Userd-defined variables interpolated into a query are treated as if you had use a string literal, not an identifier. The query you show would be like:
SELECT * FROM 'mytable'
That is of course not correct syntax. You can't select from a string literal.
Table names (and any other identifers) must be fixed at the time the query is parsed. So you can't make a query that names a table using a parameter, an expression, a subquery, or anything else. The table identifier must be plain and fixed before any data is read.
If you need to use a variable table name, you have to do it with dynamic SQL. That is, the whole query must be a string, which you can format any way you want it. Then parse that string as SQL at runtime.
Dynamic SQL is common. This is the way virtually all SQL is run from applications. If you use Java or Python or PHP or Go or any other language, you're probably using dynamic SQL.
If you run the query in a stored procedure, you have to use PREPARE and EXECUTE, after concatenating your variable into a string to format the query:
SET #sql = CONCAT('SELECT * FROM `', #targetTableName, '`');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Using 'where..in' inside store procedure with prepared statements (Safe Way)

Im trying to secure my store procedure to avoid SQL Injection attacks using prepared
statements. with the guide that mentioned here :
"https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html"
mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET #a = 3;
mysql> SET #b = 4;
mysql> EXECUTE stmt1 USING #a, #b;
+------------+
| hypotenuse |
+------------+
| 5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;
I have no problem with passing parameter one by one.
Now if i have to pass array of item to SP from java and use 'where..in' , what is the best
approach ?
I can use something like this :
SET #somestring = '1,3,18,25';
SET #s=CONCAT("
SELECT * FROM city
WHERE id IN (",#somestring,");");
PREPARE stmt FROM #s;
EXECUTE stmt;
Dont know if is it secure enough for injection , since i guess its not checking parameter
one by one while it not use "USING #a, #b".
You cannot pass an array to your stored procedure, because MySQL doesn't support arrays. Your string '1,3,18,25' is a string that happens to contain commas. This is not an array.
Interpolating an unknown string into a dynamic SQL statement is SQL injection, full stop. You can't be sure it does not contain special characters that would change the syntax of the dynamic SQL query, so it's not safe.
The safest way to use variables in dynamic SQL statements is by using query parameters. But there's a couple of problems: I assume your string with comma-separated numbers may have a variable number of numbers, and you must support that.
Query parameters can only be used for individual scalar values. One parameter per value:
WHERE id IN (?, ?, ?, ?)
The syntax for EXECUTE stmt USING ... supports a variable number of arguments, but not a dynamic number of arguments. You must code the arguments as fixed in your code, and the arguments must be individual user-defined variables (the type with the # sigil). There's no good way to convert a string of comma-separated values into a like number of individual variables. It's possible to extract substrings in a loop, but that's a lot of code.
And it still wouldn't help because you'd have to find a way to pass a dynamic number of arguments to EXECUTE ... USING.
A common workaround for MySQL users is to use FIND_IN_SET(). This allows you to match a column to a comma-separated string of values.
WHERE FIND_IN_SET(id, '1,3,18,25') > 0
So you could pass your string as a single parameter to a prepared statement:
SET #somestring = '1,3,18,25';
SET #s='SELECT * FROM city WHERE FIND_IN_SET(id, ?)';
PREPARE stmt FROM #s;
EXECUTE stmt USING #somestring;
In fact, you don't even need to use PREPARE & EXECUTE for this. You can use MySQL variables in a query directly.
SELECT * FROM city WHERE FIND_IN_SET(id, #somestring);
This is safe, because the variable does not cause SQL injection. The query has already been parsed at the time you create the stored procedure, so there's no way the content of the variable can affect the syntax of the query, which is what we're trying to avoid.
This is safe ... but it's not optimized. By using FIND_IN_SET(), the query cannot use an index to search for the values in your string. It will be forced to do a table-scan. Probably not what you want.
So what are the options for solutions?
You could check the input string to make sure it has only digits and commas, and abort if not.
IF #somestring NOT REGEXP '^([[:digit:]]+,)*[[:digit:]]+$' THEN
SIGNAL SQLSTATE VALUE '45000'
SET MESSAGE_TEXT = 'Invalid input, please use only comma-separated integers';
FI
Once you confirm that the string is safe, then you can safely interpolate it into the query string, as in your example with CONCAT().
My preferred solution is to stop using MySQL stored procedures. I hardly ever use them, because virtually every other programming interface for MySQL is easier to code.

How to use prepare statement for Use database in Mysql

set #switch_schema= concat('use ', v6_schema, ';');
select #switch_schema;
PREPARE s3 from #switch_schema;
EXECUTE s3;
Prepare statement does not support 'Use'; is there a solution to this?
The workaround is the following but I am looking for a more robust solution
set #db := v6_schema;
drop temporary table if exists tempdb.activeUnits;
set #query = concat ('create temporary table tempdb.activeUnits
select *
from ',#db,'.activemodelunits_blue
where active_datetime = (Select max(active_datetime) from ',#db,'.ActiveModelUnits_blue) ';
PREPARE s3 from #query;
EXECUTE s3;
I'm afraid since you can't run USE as a prepared statement, your options are limited.
USE before you call this routine
You could call USE from your application before calling the procedure where you reference the table.
USE v6_schema;
CALL MyProcedure();
USE inside a CASE
If you are writing this code in a stored procedure, you can use the CASE statement.
BEGIN
CASE v6_schema
WHEN 'myschema1' THEN USE myschema1;
WHEN 'myschema2' THEN USE myschema2;
WHEN 'myschema3' THEN USE myschema3;
ELSE USE mydefaultschema;
END CASE;
END;
This means you're limited to the finite list of schemas for which you have coded. You can't make this adapt to any future schema name you think of in the future, without updating the code.
Use qualified table names
This is the workaround you mentioned in your question. Concatenate the schema name with table names, every time you reference those tables in prepared queries.

Is possible to interpret and operation on string using a mathematical function in MySQL?

I want to select the final value of a string (for example '3+4') using a SELECT. I want to know if exists a function or a way in MySQL.
Example:
SELECT ('4+1*3') as VALUE;
The result is:
VALUE
7
You can do this in three steps:
Combine query into a single string
Create a prepared statement from this string
Execute said statement
Something like this:
SET #query = CONCAT('SELECT (', '4+1*3', ') AS VALUE');
PREPARE stmt FROM #query;
EXECUTE stmt;
Note that this does not merely evaluate mathematical expressions. A malicious user could insert pretty much anything into the query here, so you are open to the worst of sql injection attacks unless you carefully sanitize the string you paste into the query to only allow mathematical expressions.
Note that I can think of no application where this kind of operation would be useful. I'd say if you have to evaluate arbitrary strings, you're probably better of doing so in application code, not in the database.

problem with prepare statement

I write this query and it has error what is problem?
prepare test from
'select * from ?';
what is problem?
what is it's correct form?
You can't just put a placeholder wherever you like. Parameter placeholders can appear only in those places inside the statement where you would normally expect an expression. In particular, you cannot use parameter placeholders to parameterize identifiers or entire statement structures. That's why your attempt fails.
Many more useful things regarding prepared statements and Dynamic SQL in MYSQL can be found in Roland Bouman's blog -> MySQL 5: Prepared statement syntax and Dynamic SQL.
If your intended use is something like:
prepare test
from
'select * from ?' ;
set #myt := 'myTable' ;
execute test
using #myt ;
it will simply not work. But you can bypass it with:
set #myt := 'myTable'
set #qtext := concat('select * from ',#myt) ;
prepare test
from #qtext ;
execute test ;
I've never tried having the table name as a variable. I'm not sure that's allowed. Try the following:
PREPARE test FROM "SELECT * FROM table_name WHERE column = ?";
This is kind of a stab in the dark, since you're not providing the error message.