Can you create a table in mysql with dots in it? - mysql

Can you create a table in mysql with dots (.) in it?
I´m having trouble manipulating a table with a dot in its name. I did it this way as a shortcut for a php query.

You can create table names with punctuation by delimiting the identifiers with back-ticks.
mysql> create table `my...table` (id serial primary key);
Query OK, 0 rows affected (0.05 sec)
mysql> insert into `my...table` values (1234);
Query OK, 1 row affected (0.02 sec)
mysql> select * from `my...table`;
+------+
| id |
+------+
| 1234 |
+------+
It's legal, but probably more trouble than it's worth. You have to remember to use the back-ticks every time you reference the table.
A good compromise is to use _ instead of a dot, because you don't have to delimit the table name for that character.

You could quote the table name(s) with back-ticks — or, if you have control over it, and it's not too late, substitute the special characters with a standardized alternative:
select * from `table.name`
Permissible characters (without the need for quotes):
[0-9,a-z,A-Z$_]

Related

Don't use identifier quoting in ORM Doctrine

There is a Best Practices page in official Doctrine documentation.
https://www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/best-practices.html#don-t-use-identifier-quoting
It's said: "Don't use identifier quoting". I don't quite understand that. Can you explain me what is identifier quoting and why it's not rocommended to use it? What to use instead? Please write some SQL queries for the example.
Normally you can't make a table whose name conflicts with an SQL reserved keyword, or contains punctuation or whitespace.
mysql> CREATE TABLE interval (begin INT, end INT);
ERROR 1064 (42000): You have an error in your SQL syntax ...
near 'interval (begin INT, end INT)'
But you can delimit an identifier with back-ticks (or double-quotes in standard SQL) to allow tables with normally illegal names.
mysql> CREATE TABLE `interval` (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)
Doctrine is recommending that you solve this problem by just avoiding naming your tables in a way that requires them to be delimited. They are not specific about the edge cases they think will happen.
One could be if you try to create a table whose name contains a literal back-tick character. This is permitted too, but it requires care to escape the back-tick.
mysql> create table `my``table` (begin INT, end INT);
Query OK, 0 rows affected (0.03 sec)
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| my`table |
+----------------+
The other problem is that you must remember to delimit illegal table names in every query that references them. Since Doctrine generates a lot of SQL, it's possible they don't think they can do this consistently, and their solution is to put the responsibility on you to avoid the issue.
Their solution to avoid tables that have reserved words has a problem: every release of MySQL has new reserved words. A table that is allowed in MySQL 5.7 may conflict with a new reserved word in MySQL 8.0. If you can't delimit table names, then you must study the list of new reserved words in 8.0 and rename tables before you upgrade.
In fact, in the MySQL 8.0 era, they are more comfortable introducing new backward-incompatible features in minor releases, so there could be new reserved words introduced at any time. For example, FULL was made a keyword in MySQL 8.0.32, so it now generates a warning:
mysql> create table full ( i int);
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show warnings;
+---------+------+----------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------------------------------------------------------+
| Warning | 4119 | Using FULL as unquoted identifier is deprecated, please use quotes or rename the identifier. |
+---------+------+----------------------------------------------------------------------------------------------+

MySQL "old version syntax"

im currently porting my SQLite database to MySQL, just made a script to change all INSERT's and more to MySQL but im sometimes getting an "old version syntax error":
INSERT INTO players(id, name) VALUES (21457, '/Gohst_Killer67\');
The Database structure:
CREATE TABLE IF NOT EXISTS players (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(40))
I have alot usernames saved, but those / or \ keeps raising those error messages. I hope theres a way to fix it without editing all names which contain / or .
Thanks
In mysql the way is-
Hitesh> CREATE TABLE IF NOT EXISTS players (id INTEGER PRIMARY KEY AUTO_INCREMENT, name VARCHAR(40));
Query OK, 0 rows affected (0.21 sec)
Hitesh> INSERT INTO players(id, name) VALUES (21457, '/Gohst_Killer67\'');
Query OK, 1 row affected (0.04 sec)
for special character you should use \ before it. like i have used \' in insert.
You can disable backslash escapes by setting NO_BACKSLASH_ESCAPES in the SQL mode:
SET #old_sql_mode=##sql_mode;
SET ##sql_mode=CONCAT_WS(',', ##sql_mode, 'NO_BACKSLASH_ESCAPES');
Hitesh> INSERT INTO players(id, name) VALUES (21457, "/Gohst_Killer67'");
Query OK, 1 row affected (0.04 sec)
for insert single quote you can put string in "" when insert or vice versa like i did. other wise you can use quote function quote

MySQL - how do I unhex a field rather than a string?

I've got a table which contains a varchar(1024) field, which in that contains strings which has hex encoded strings. This table is filled automatically and I have to provide an SP to allow users to download this, therefore, I need to change the hex back into human readable form.
If I manually run this statement (taking the Hex data from the field), it works just fine:
SELECT X'5468697320697320612074657374206D6573736167652031323334353637383930';
But I cannot find a working example of getting this to work when calling the field/column name. I've found a few examples, but these just return a null or 0.
I've tried X and UnHex() and neither give me a result.
Where am I going wrong?
Thanks
EDIT:
Okay, after doing a bit more testing, it appears it must be the way it's being written to the database in the first place.
It's a Classic ASP page that calls an SP, which creates the database entry. In this method, the write to the DB works, and I can see the HEX content in the field. Copying the content of the field, and putting this into a Select X'123123' gives me the ASCII values, as I want.
If I try this as a Select, this fails, giving me a zero or Null return.
SELECT Message_Body_Hex, UNHEX(Message_Body_Hex) FROM messages_inbound
returns:
Message_Body_Hex......unhex(Message_Body_Hex)
417265612032........(NULL)
Still confused! :)
I realize this is an old question but I ran into this same problem today and solved it using a combination of HEX and CAST. Using your example, try this:
SELECT HEX(CAST(X'5468697320697320612074657374206D6573736167652031323334353637383930' AS CHAR(33)))
When pulling from a table you'd substitute the field name:
SELECT HEX(CAST(binary_field AS CHAR(33)))
I've seen other answers recommending to use MAX in place of the 33 but this appears to work fine. Here are some sources I used:
SQL Server converting varbinary to string
and
How to convert from varbinary to char/varchar in mysql
Using the UNHEX() function seems to work fine on MySQL 5.5.29-1:
mysql> create table t1 ( f1 varchar(1024) );
Query OK, 0 rows affected (0.03 sec)
mysql> insert into t1 values('5468697320697320612074657374206D6573736167652031323334353637383930');
Query OK, 1 row affected (0.02 sec)
mysql> select f1 from t1;
+--------------------------------------------------------------------+
| f1 |
+--------------------------------------------------------------------+
| 5468697320697320612074657374206D6573736167652031323334353637383930 |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select unhex(f1) from t1;
+-----------------------------------+
| unhex(f1) |
+-----------------------------------+
| This is a test message 1234567890 |
+-----------------------------------+
1 row in set (0.00 sec)

MySQL LIKE operator with wildcard and backslash

It's frustrated with MySQL's pattern escaping used in LIKE operator.
root#dev> create table foo(name varchar(255));
Query OK, 0 rows affected (0.02 sec)
root#dev> insert into foo values('with\\slash');
Query OK, 1 row affected (0.00 sec)
root#dev> insert into foo values('\\slash');
Query OK, 1 row affected (0.00 sec)
root#dev> select * from foo where name like '%\\\\%';
Empty set (0.01 sec)
root#dev> select * from foo;
+------------+
| name |
+------------+
| with\slash |
| \slash |
+------------+
2 rows in set (0.00 sec)
root#dev> select * from foo where name like '%\\\\%';
Empty set (0.00 sec)
root#dev> select * from foo where name like binary '%\\\\%';
+------------+
| name |
+------------+
| with\slash |
| \slash |
+------------+
2 rows in set (0.00 sec)
According to MySQL docs: http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html#operator_like
%\\\\% is the right operand, but why it yields no result?
EDIT:
The database I'm testing that in has character_set_database set to utf8. To further my investigation, I created the same setup in a database that has character_set_database set to latin1, and guess what, '%\\\\%' works!
EDIT:
The problem can be reproduced and it's the field collation problem. Details: http://bugs.mysql.com/bug.php?id=63829
In MySQL 5.6.10, with the text field collation utf8mb4_unicode_520_ci this can be achieved by using 5 backslash characters instead of 4, i.e:
select * from foo where name like binary '%\\\\\%';
Somehow, against all expectations, this properly finds all rows with backslashes.
At least this should work until the MySQL field collation bug above is fixed. Considering it's been more than 5 years since the bug is discovered, any app designed with this may outlive its usefulness before MySQL is even fixed - so should be a pretty reliable workaround.
With MySQL 5.0.12 dev on Windows 10 I got the following results when I changed the query from
SELECT * FROM `foo` WHERE `name` LIKE '%http:\/\/%'
to
SELECT * FROM `foo` WHERE `name` LIKE '%http:\\\\\\\%'
it works and yet the first string with forward slashes was the original field content. It seems to have interpreted forward slashes as backslashes.
It seems it has some relation to that MySQL bug: http://bugs.mysql.com/bug.php?id=46659
I think you connect to mysql not specifying correct --character-set-server option (which defaults to latin1 with collation latin1_swedish_ci), and having utf-8 as the current charset of the console. That causes incorrect char conversions and comparisons when you deal with data which supposed to be converted to the utf8 from the charset of --character-set-server.

MySQL query returns 0 rows when searching for value with dot (.) in string

If I try to search for a value in mysql database and the string value contains dot in it, query returns 0 rows. Example:
SELECT * FROM table WHERE `username`='marco.polo' --> 0 rows
SELECT * FROM table WHERE `username` LIKE '%.polo%' --> 0 rows
SELECT * FROM table WHERE `username` LIKE 'polo' --> Success
This appeared after moving server and database to another place. I know that dot is a set of extended regular expressions, but it should not apply to equal nor LIKE operator, simply because I don't use REGEXP in query.
I've tested the same query on my local database and it works fine.
Could there be a special setting in mysql that treats dot differently than it usually does?
user1084605, I tried to replicate the problem (using MySQL version 5.1.37), but got exactly the opposite results as you. See below:
mysql> create table test (username varchar(100));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test values ('marco.polo');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM test WHERE `username`='marco.polo';
+------------+
| username |
+------------+
| marco.polo |
+------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM test WHERE `username` LIKE '%.polo%';
+------------+
| username |
+------------+
| marco.polo |
+------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM test WHERE `username` LIKE 'polo';
Empty set (0.00 sec)
According to the MySQL docs, the only special characters when using the LIKE operator are "%" (percent: matches 0, 1, or many characters) and "_" (underscore: matches one and only one character).
http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html
A "." (period) does have special meaning for MySQL's REGEXP operator, but it should still match a literal period in your column.
http://dev.mysql.com/doc/refman/5.0/en/regexp.html
Can you replicate the SQL statements I ran above and paste your results in reply?
As #cen already mentioned, character set can causes that problem.
I have had this sample:
`email` VARCHAR(45) CHARACTER SET 'armscii8' NOT NULL,
this is was in the .sql dump, which I receive.
So, when I was trying to fetch object with this email
I couldn't get it.
The below query takes care of the scenario when we have only DOT operator in the columns.
SELECT * FROM test WHERE `username` LIKE '%.%';