Variable column names using prepared statements
Solution 1
This indicates a bad DB design. The user shouldn't need to know about the column names. Create a real DB column which holds those "column names" and store the data along it instead.
And any way, no, you cannot set column names as PreparedStatement
values. You can only set column values as PreparedStatement
values
If you'd like to continue in this direction, you need to sanitize the column names (to avoid SQL Injection) and concatenate/build the SQL string yourself. Quote the separate column names and use String#replace()
to escape the same quote inside the column name.
Solution 2
Prepare a whitelist of allowed column names. Use the 'query' to look up in the whitelist to see if the column name is there. If not, reject the query.
Solution 3
The accepted answer is not actually correct. While the OP approach indicated a bad DB design, it might be required by the business logic (for instance a MySQL IDE)
Anyway, for MySQL prepared statements, what you need to know is that ?
is for values, but if you need to escape column names, table names etc, use ??
instead.
Something like this will work:
SELECT ??, ??, ?? FROM ?? WHERE ?? < ?
Set values to ['id', 'name', 'address', 'user', 'id', 100]
Solution 4
I think this case can't work because the whole point of the prepared statement is to prevent the user from putting in unescaped query bits - so you're always going to have the text quoted or escaped.
You'll need to sanitize this input in Java if you want to affect the query structure safely.
KLee1
Note: My views are not necessarily representative of my company's.
Updated on July 09, 2022Comments
-
KLee1 almost 2 years
I was wondering if there was any way to specify returned column names using prepared statements.
I am using MySQL and Java.
When I try it:
String columnNames="d,e,f"; //Actually from the user... String name = "some_table"; //From user... String query = "SELECT a,b,c,? FROM " + name + " WHERE d=?";//... stmt = conn.prepareStatement(query); stmt.setString(1, columnNames); stmt.setString(2, "x");
I get this type of statement (printing right before execution).
SELECT a,b,c,'d,e,f' FROM some_table WHERE d='x'
I would, however, like to see:
SELECT a,b,c,d,e,f FROM some_table WHERE d='x'
I know that I cannot do this for table names, as discussed here, but was wondering if there was some way to do it for column names.
If there is not, then I will just have to try and make sure that I sanitize the input so it doesn't lead to SQL injection vulnerabilities.
-
KLee1 almost 14 yearsWell, the user doesn't actually need to know the column names, but the column names needed are deduced based on forms submitted by the user. This is handled on the client side, though, so I wanted to see if there was some way to ensure the data is safe. Should I then just move the whole lot to the server-side, thereby ensuring the column data is untainted?
-
BalusC almost 14 yearsHandle it on the server side instead. Don't do business stuff in client side.
-
specializt almost 9 years@BalusC : "you cannot set column names as PreparedStatement values" - thats completely made up. Using column names inside of prepared statement value-lists is of course possible - but that doesnt mean it should be used that way, it still is bad design.
-
npn_or_pnp about 8 yearsI'd like to see you dynamically limit fields for a given resource using REST with JSON. Not everybody wants the whole resource returned, and not everybody wants to create 1,000 queries for every permutation of said columns.
-
Insac over 7 yearsYou're right on the "it can't work". However the first reason for PreparedStatement was because of resource efficiency, allowing to keep a statement cached and submitting it multiple times just changing the values (great especially for OLTP). Its resilience to SQL Injection attempts is a very desiderable side effect.
-
Anil Agrawal about 7 yearsYour answer looks ok, but you should describe your code as well
-
Clement Cherlin almost 7 yearsThis answer leads directly to an SQL injection attack.
-
Admin over 6 yearsWhat about dynamic ordering for a query utilizing variable column name? Would that also be considered bad design?
-
Guillaume Husta almost 6 yearsYes this is an example of vulnerable code, as described here : find-sec-bugs.github.io/bugs.htm#SQL_INJECTION_JPA
-
nanosoft about 5 yearsThe question is about leveraging preparedStatement(). Your solution doesn't use it. It is prone to sql injection.
-
where_ about 4 yearsIt's a very interesting comment. I couldn't find any reference to that escaped parameter value syntax (??). Could you, possibly, point me to one?
-
DraganescuValentin about 4 yearsI don't remember where I've seen this, definitely not in the official docs. However, I'm using this successfully in a toy project.
-
ceving over 3 yearsOuch! SQL code generation by string concatenation without escaping! Please delete this before you boss recognizes, that you wrote this.
-
Yami Odymel over 2 yearsI think this is a specified usage for Node.js packaged named mysqljs/mysql
-
DraganescuValentin over 2 years@YamiOdymel Indeed this might only work on the mysqljs/mysql Node.js package. It looks like the select is not valid when run from MySQLWorkbench This statements do not work because
??
is not recognisedPREPARE stmt1 FROM 'SELECT ??, ?? FROM ?? WHERE ?? = ?'; SET @a = 'foo'; SET @b = 'bar'; SET @c = 'Foos'; SET @d = 'foo'; SET @e = 'fooooo'; EXECUTE stmt1 USING @a, @b, @c, @d, @e;