Difference in behavior on CONCAT_WS between systems - mysql

So, this is a simple situation but I wanted to understand what's causing this issue. I have the following code (modified for example):
SELECT `Transactions`.*, CONCAT_WS(" ", `People`.`first_name`, `People`.`last_name`) AS full_name ...
On my local machine I have:
Windows 10
Apache 2.4.25
PHP 7.4.11
MySQL 5.7.25
With that combination the following code works fine.
On the remote server I have:
Ubuntu 20.04.1 LTS
Apache 2.4.41
PHP 7.4.3
MySQL 8.0.19
So, I have a section which uses a data table and the data table uses server-side processing to obtain the information. On my local it shows the information correctly, but on my remote server I always got an empty array. So I tried executing the same SQL command in my remote server and I got this error:
#1054 - Unknown column ' ' in 'field list'
My SQL was correctly formed so I thought maybe the problem was related to the CONCAT_WS function.
So I decided to modify it to:
SELECT `Transactions`.*, CONCAT_WS(' ', `People`.`first_name`, `People`.`last_name`) AS full_name ...
I basically changed CONCAT_WS(" ", to CONCAT_WS(' ', and the code worked as intended.
I am not sure if this affects in some way, but is this a MySQL change in requirements for the usage of CONCAT_WS or something else?
Is it ok if I use it with single quotes elsewhere?

I suggest you run this on both systems:
SELECT ##sql_mode;
You will find that on your 8.0 server, the sql mode includes either the modes ANSI or ANSI_QUOTES.
Explanation:
The double-quotes have different meanings in MySQL depending on which sql mode is in effect.
By default, double-quotes are the same as single-quotes: they delimit a string literal.
If the sql mode is ANSI or ANSI_QUOTES, then the double-quotes delimit an identifier, acting like the back-ticks.
So the same code can behave differently on different MySQL instances. This has nothing to do with the difference between 5.7 and 8.0, because the sql mode behaves the same on these two versions. Neither version enables the ANSI or ANSI_QUOTES modes by default, so you or someone else must have enabled that mode on your 8.0 server.
This is why in this expression:
CONCAT_WS(" ", ...)
The first argument " " is treated as a string literal on one server, and on the other server it is treated as a column whose name is (which is legal SQL, even if it's weird).
It's safest to always use single-quotes to delimit a string literal, and to always use back-ticks to delimit an identifier.
Never use double-quotes for either case in MySQL, because your code that uses double-quotes in SQL queries will break if someone changes the sql mode.

Related

sybase escape character

I have an update query that updates a column that holds another application SQL query.
Putting SQL inside has been problematic I wanted to resolve it with escape characters.
update
my_table
set
sql_column = 'UPDATE inner_table SET user_name=\'user_name\' text=\'this this free text with things like \" inside it and drives me made\''
where
condition_col = 123456
The above is correct in any SQL syntax checker; however, Sybase throws an error simply Incorrect syntax new 'username.'
I am new to Sybase; please help.
I was expecting that Sybase would behave like MySQL, which is different.
Sybase (and ansi-standard SQL*) escapes the single quote with itself. You don't need to do anything special with a double quote inside a string literal (since in ansi-standard SQL double quotes do not create literals).
sql_column = 'UPDATE inner_table SET user_name=''user_name'' text=''this this free text with things like \\" inside it ...'
But Sybase will NOT behave like MySQL (it's far more standards compliant).
Lacking some context here, but this kind of code is also likely to end up leaving you dangerously susceptible to SQL injection issues, and that's a really big deal.
* The link is for Informix, but it does a good job explaining the standard

Convert and extract row using mysql and regular expression pattern

How do I to extract a converted value from my db?
SELECT name FROM clients LIMIT 1;
It will list: "13's Automotors"
But I want to show "13SAUTOMOTORS", listing only letters and numbers without spaces.
Server type: Percona Server Server version: 5.6.40-84.0-log - Percona
Server (GPL), Release 84.0, Revision 47234b3 Protocol version: 10
Newer versions (MySQL 8 and MariaDB 10+) support the REGEXP_REPLACE() function.
SELECT regexp_replace(name, '[^\\d\\w]', '') as converted_name
FROM clients
will replace all non-digit and non-word characters with an empty string.
If you need the result in uppercase, use UPPER()
SELECT upper(regexp_replace(name, '[^\\d\\w]', '')) as converted_name
FROM clients
db<>fiddle demo
If your version doesn't support REGEXP_REPLACE(), consider to do the conversion in your application language. Since you've tagged your question with mysqli, I assume that you are using PHP. Then you can use pred_replace() and strtoupper():
$row['converted_name'] = preg_replace('/[^\\d\\w]/', '', $row['name']);
$row['converted_name'] = strtoupper($row['converted_name']);
rextester demo
In older versions of MySQL you can use a bunch of nested replace operations for this.
SELECT UPPER(REPLACE(REPLACE('3''s Automotors', ' ',''),'''','')) val
It's a bit nasty because you need a nested REPLACE for each possible character you want to remove, but it works.
Notice you must represent single-quote characters ' in string constants in MySQL queries by doubling them. So, '''' represents the single character ' as a string constant.

MySQL Workbench "->" Support

It looks like MySQL Workbench is now supporting JSON functionality, however I'm still seeing parser errors on MySQL 5.7.9 functionality, such as the "->" operator.
When I use the following query, I'm getting a syntax error over the "$.test" portion:
Record
record: {"test": 123}
Query
SELECT test->"$.test" FROM table
The query still executes successfully, however I'm curious as to why the syntax parser is incorrectly showing an error.
OK, the problem is probably something else than what I posted in my comments. You are using double quotes, which represent strings only if the ANSI quotes are not enabled (then they wrap identifiers). Use single quotes instead.

smart solution of SQL injection

These is one keyword confliction issue in the query module of my application,please see if you can tell me a smart solution.
First,In query module,each query condition contains three parts in UI:
1.field name,its value is fixed,e.g origin,finalDest...
2.operator,it is a select list which includes "like","not like","in","not in","=","!="
3.value,this part is input by user.then in back-end,it will assemble the SQL statement according to UI's query criteria,e.g if user type/select following stuff in UI
Field Name Operator Value
origin like CHI
finalDest in SEL
In back-end,it will generate following SQL:
select * from Booking where origin like '%CHI%' and finalDest in ('SEL').
But there is a bug,e.g if user type some of special symbol in "value",e.g "'","_" etc,it will lead to the generated SQL also contain ' or _ ,e.g:
select * from Booking where origin like '%C_HI%' and finalDest in ('S'EL').
you could see as there is special symbol in "where" block,the SQL can't be executed
For this problem,my solution is add escape character "/" in front of the special symbol before executing it,but what i know is just ' or _ that would conflict with the SQL keywords,do you know if there is any others similar symbol that i need to handle or do you guys have any better idea that can avoid the injection
Sorry,forgot told you what language i am using,i am using java,the DB is mysql,i also use hibernate,there are a lot of people said why i didn't use PreparedStatement,this is a little complex,simply speaking,in my company,we had a FW called dynamic query,we pre-defined the SQL fragment in a XML file,then we will assemble the SQL according to the UI pass in criteria with the jxel expression,as the SQL is kinda of pre-defined stuff,i afraid if change to use PreparedStatement,it will involve a lot of change for our FW,so what we care is just on how to fix the SQL injection issue with a simple way.
The code should begin attempting to stop SQL injection on the server side prior to sending any information to the database. I'm not sure what language you are using, but this is normally accomplished by creating a statement that contains bind variables of some sort. In Java, this is a PreparedStatement, other languages contains similar features.
Using bind variables or parameters in a statement will leverage built in protection against SQL injection, which honestly is going to be better than anything you or I write on the database. If your doing any String concatenation on the server side to form a complete SQL statement, this is an indicator of a SQL injection risk.
0 An ASCII NUL (0x00) character.
' A single quote (“'”) character.
" A double quote (“"”) character.
b A backspace character.
n A newline (linefeed) character.
r A carriage return character.
t A tab character.
Z ASCII 26 (Control+Z). See note following the table.
\ A backslash (“\”) character.
% A “%” character. See note following the table.
_ A “_” character. See note following the table
Reference
Stack Similar Question
You should use bind variables in your SQL statement. As already mentioned this is done with PreparedStatements in Java.
To make sure, only valid column names are used, you can validate the input against the database. MySQL provides schema information like columns of each table as part of the INFORMATION_SCHEMA. For further information, check the MySQL documentation:
"The INFORMATION_SCHEMA COLUMNS Table"

SQL exception with 'from' as a column name

I have a table with a column named 'from'. I want to retrieve data from it and so I tried following query.
select title,from,grade from localcourses where title='new';
But I get following exception due to the column name 'from'.
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,grade from localcourses where title='new'
How can I avoid this without renaming the column name? Thank you.
Try --
select `title`,`from`,`grade` from localcourses where `title`='new';
If you are running MySQL in standard (ANSI) mode, use double quotes to "escape" the keyword:
select title,
"from",
grade
from localcourses
where title='new';
If you are running MySQL in non-standard mode (which is still the default if I'm not mistaken), you need to use MySQL's dreaded "backticks:
select title,
`from`,
grade
from localcourses
where title='new';
On MySQL you can use the ` (back apostrophe -- to the left of the 1 key on your keyboard). Use
`from`.
I'll be the first to say it - you should avoid naming tables, columns, triggers, procedures, functions, etc with the names of reserved, action, and other commonly used words in sql and database engine syntax. It only creates confusion such is the case here.
Assuming Oracle try
select title,"from",grade from localcourses where title='new';
In mySQL, you need to enclose the from column in backtick character
select title,`from`,grade from localcourses where title='new'
I suspect the backtick character you are using is not the right one, I am not sure what type of keyboard you have, so it might not send the proper character in.
Try this instead.
select title,localcourses.from,grade from localcourses where title='new'
and see if that helps