Server version: 10.1.21-MariaDB-1~jessie
select 'a%b' like '%\%\%';
+--------------------+
| 'a%b' like '%\%\%' |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.00 sec)
the like clause represents 'wildcard + literal % + literal %' but it matches 'a%b'.
or
select 'a%b' like '%\%\%\%\%\%';
+--------------------------+
| 'a%b' like '%\%\%\%\%\%' |
+--------------------------+
| 1 |
+--------------------------+
1 row in set (0.00 sec)
MySQL 5.5.38 returns 0 for both statements. Is the syntax of MariaDB different?
Add
#rahul pointed that the syntax is wrong, so I created a dummy table and ran
SELECT * FROM `table1` where 'a%b' like '%\%\%';
which matches every row in the table.
However, a row with field1='a%b' doesn't match when I ran
SELECT * from `table` where field1 like '%\%\%';
Now going to test on 10.1.22.
It seems this is fixed in 10.1.22.
Server version: 10.1.22-MariaDB-1~xenial mariadb.org binary distribution
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> select 'a%b' like '%\%\%';
+--------------------+
| 'a%b' like '%\%\%' |
+--------------------+
| 0 |
+--------------------+
1 row in set (0.00 sec)
Related
I want to print query by MySQL's version in .sql file.
When I use MySQL version 5.6, want to print (2 column)
SELECT user, host FROM mysql.user;
or, I use MySQL version 5.7 or 8, want to print (3 column)
SELECT user, host, account_locked FROM mysql.user;
Because MySQL 5.6 version doesn't have account_locked column.
mysql> SELECT * FROM information_schema.GLOBAL_VARIABLES WHERE variable_name = 'version';
+---------------+-----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+---------------+-----------------+
| VERSION | 5.6.22-71.0-log |
+---------------+-----------------+
1 row in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'version';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| version | 5.6.22-71.0-log |
+---------------+-----------------+
1 row in set (0.00 sec)
mysql> SELECT ##version;
+-----------------+
| ##version |
+-----------------+
| 5.6.22-71.0-log |
+-----------------+
1 row in set (0.00 sec)
In a Stored Procedure, you can do something like
IF (##version < "5.7") THEN
SELECT user, host FROM mysql.user;
ELSE
SELECT user, host, account_locked FROM mysql.user;
ENDIF;
It gets messier if you also need to handle MariaDB, with its "10.x.y". And, if Percona has any differences, you need to dig deeper into the "version".
I've got probably what is a very simple issue. However, I've researched extensively and haven't found a solution yet. Basically, I want to convert a modified string variable into the DATE format (specifically %Y).
I have a column variable called dob, which includes dates in the VARCHAR format. The values of these strings vary and can look like any of the following: 01 JAN 1900, ABT 1960, or Unknown. Nonetheless, the year is always the last four digits, so I'm grabbing the year by creating a substring. But I want to convert that substring into a YEAR format. My thought is that I need to use str_to_date to accomplish this.
This is my MySQL query:
SELECT dob, STR_TO_DATE(SUBSTRING(dob, -4), "%Y") as YEAR
FROM person_table;
Upon running it, I only get NULL values. Is there something I'm missing?
Here are my MySQL specs:
innodb_version: 5.7.20
protocol_version: 10
Thanks for your help!
Edit: Providing SQL Mode Information:
+---------------+-----------------------------------------------------------+
| Variable_name | Value |
+ --------------+-----------------------------------------------------------+
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+------------------------------------------------------------
1 row in set (0.00 sec)
Upon running the query SELECT STR_TO_DATE('2009','%Y'); I get NULL and the following warning:
I get the following warning:
+---------+------+-----------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------+
| Warning | 1411 | Incorrect datetime value: '2009' for function str_to_date |
+---------+------+-----------------------------------------------------------+
1 row in set (0.00 sec)
str_to_date returns a date type, and only a year is an incomplete date. str_to_date will fill in the incomplete parts with zeroes unless you have no_zero_dates mode enabled. This is part of Strict SQL Mode which is the default in MySQL 8.0; it avoids the worst of MySQL's quirks.
Strict mode controls how MySQL handles invalid or missing values in data-change statements such as INSERT or UPDATE. A value can be invalid for several reasons. For example, it might have the wrong data type for the column, or it might be out of range
Without Strict SQL Mode, MySQL will turn "2009" into the invalid date 2009-00-00.
mysql> set sql_mode = '';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT STR_TO_DATE('2009','%Y');
+--------------------------+
| STR_TO_DATE('2009','%Y') |
+--------------------------+
| 2009-00-00 |
+--------------------------+
1 row in set (0.00 sec)
With Strict SQL Mode it will not.
mysql> show variables like 'sql_mode';
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT STR_TO_DATE('2009','%Y');
+--------------------------+
| STR_TO_DATE('2009','%Y') |
+--------------------------+
| NULL |
+--------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+-----------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------+
| Warning | 1411 | Incorrect datetime value: '2009' for function str_to_date |
+---------+------+-----------------------------------------------------------+
1 row in set (0.00 sec)
To solve your problem, instead of trying to do a one-size-fits-all conversion, I would recommend trying several formats from most to least specific using coalesce. You will have to add the missing date parts as needed.
select coalesce(
str_to_date(dob, '%d %b %Y'),
str_to_date(concat(dob, '-01-01'), 'ABT %Y-%m-%d')
)
from person_table;
As this is very ugly to do, I also would recommend adding a proper date column and doing an update to convert from the messy string dates to proper dates. Then query the new column going forward.
alter table person_table add column dob_date date;
update person_table
set dob_date = coalesce(
str_to_date(dob, '%d %b %Y'),
str_to_date(concat(dob, '-01-01'), 'ABT %Y-%m-%d')
)
where dob_date is null;
You can then check for people with a null dob_date, examine their dob field, and adapt your conversion. Iterate as needed.
UPDATE
To add, yes, I need the year 2020 as opposed to the string. The reason being is because I need to compare the year values.
As strings they will not compare as you need. Strings compare character by character. '200' is greater than the string '1999'.
mysql> select '1999' < '2000';
+-----------------+
| '1999' < '2000' |
+-----------------+
| 1 |
+-----------------+
1 row in set (0.00 sec)
mysql> select '1999' < '200';
+----------------+
| '1999' < '200' |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)
You need to cast them to signed integers.
mysql> select cast("1999" as signed) < cast('2000' as signed);
+-------------------------------------------------+
| cast("1999" as signed) < cast('2000' as signed) |
+-------------------------------------------------+
| 1 |
+-------------------------------------------------+
1 row in set (0.00 sec)
mysql> select cast("1999" as signed) < cast('200' as signed);
+------------------------------------------------+
| cast("1999" as signed) < cast('200' as signed) |
+------------------------------------------------+
| 0 |
+------------------------------------------------+
1 row in set (0.01 sec)
So your query would be...
select dob, cast(substring(dob, -4) as signed) as year
from person_table;
I am running MySQL 5.7 and wanted to convert some strings to date. I referred the manual here:
http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_str-to-date
And tried out the following(please note the MySQL version)
mysql> SELECT STR_TO_DATE('9','%m');
+-----------------------+
| STR_TO_DATE('9','%m') |
+-----------------------+
| NULL |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+--------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------+
| Warning | 1411 | Incorrect datetime value: '9' for function str_to_date |
+---------+------+--------------------------------------------------------+
1 row in set (0.00 sec)
But from the online manual for MySQL 5.7, I should see the following:
mysql> SELECT STR_TO_DATE('9','%m');
-> '0000-09-00'
Is there something that I'm missing, or could this be a bug?
As it says in the manual,
If the NO_ZERO_DATE or NO_ZERO_IN_DATE SQL mode is enabled, zero dates or part of dates are disallowed. In that case, STR_TO_DATE() returns NULL and generates a warning
That causes the result to be NULL in cases such like this, because your partial “date” contains zero values.
So I've installed common_schema to my mysql server and tried to do action with get_option function.
My SQL:
SELECT *, ((get_option("program_invested_details", "received") * 100) / get_option("program_invested_details", "invested")) AS PERCENT_TOTAL FROM hp_programs_list WHERE program_add_status = 4 AND program_status = 1 ORDER BY PERCENT_TOTAL DESC
but it seems, that get_option function doesn't work, becouse I got this error:
FUNCTION hyips_database.get_option does not exist
my DB structure:
A little test:
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8
Server version: 5.5.31-0ubuntu0.13.04.1 (Ubuntu) Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| common_schema |
| mydb |
| mysql |
| performance_schema |
| test |
+--------------------+
6 rows in set (0.00 sec)
mysql> SELECT * FROM `common_schema`.`status`\G
*************************** 1. row ***************************
project_name: common_schema
version: 2.2
revision: 523
install_time: 2015-01-01 00:00:01
install_success: 1
base_components_installed: 1
innodb_plugin_components_installed: 1
percona_server_components_installed: 0
install_mysql_version: 5.5.31-0ubuntu0.13.04.1
install_sql_mode: NO_AUTO_VALUE_ON_ZERO
1 row in set (0.00 sec)
mysql> USE `test`;
Database changed
mysql> SELECT `get_option`('{name: "Wallace", num_children: 0, "pet": Gromit}', 'pet') `result`;
ERROR 1305 (42000): FUNCTION test.get_option does not exist
mysql> SELECT `common_schema`.`get_option`('{name: "Wallace", num_children: 0, "pet": Gromit}', 'pet') `result`;
+--------+
| result |
+--------+
| Gromit |
+--------+
1 row in set (0.00 sec)
I need to insert file directories into a column but when i select (*) after inserting them all the back slashes have gone. does anyone know how i can do this. it is not possible for me to escape the slashes as i have thousands of records. I thought mysql required the user to do this using a remove_slases or something in php
The easy way to do this in MySQL is by setting the NO_BACKSLASH_ESCAPES SQL mode. Do this for the session with SET SESSION sql_mode='NO_BACKSLASH_ESCAPES';
As such:
mysql> SELECT ##SESSION.sql_mode;
+--------------------+
| ##SESSION.sql_mode |
+--------------------+
| |
+--------------------+
1 row in set (0.00 sec)
mysql> select 'don\t';
+------+
| don |
+------+
| don |
+------+
1 row in set (0.00 sec)
mysql> SET SESSION sql_mode='NO_BACKSLASH_ESCAPES';
Query OK, 0 rows affected (0.00 sec)
mysql> select 'don\t';
+-------+
| don\t |
+-------+
| don\t |
+-------+
1 row in set (0.00 sec)
This allows you to insert c:\bla\tla\bla without the \b or \t being interpreted as a string literal. Also take a look at QUOTE() if you need 'escaping' alike mysql_real_escape_string
More information at http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_no_backslash_escapes