SQL "SELECT" Command Not Working, even though entry is in DB - mysql

I have created the following database:
CREATE TABLE QuizRepo (
User_ID BIGINT AUTO_INCREMENT PRIMARY KEY,
Name TEXT
)
I populate it via JDBC, and when I populate it, I get:
mysql> select * from QuizRepo;
| User_ID | Name |
| 1 | "XXQuiz"|
When I do the following command, it works as expected:
mysql> select * from QuizRepo where USER_ID=1;
User_ID | Name |
| 1 | "XXQuiz"|
However, when I do the following command, I get a weird result
mysql> select * from QuizRepo where Name="XXQuiz";
Empty set (0.01 sec)
Has anyone seen this happen before? How could this be possible? Perhaps I am adding it in the DB incorrectly (doesnt seem likely) but then you can clearly see there is an entry called "XXQuiz" so why is it not finding it?

It looks like you've stored the quotes as well. So you'll need to so a :
select * from QuizRepo where Name = "\"XXQuiz\"";
or similar.

Could be you name don't match exactly check for this and try also
select * from QuizRepo where Name like "%XXQuiz%";

Related

MySQL select statement with tablename derived from database query

I want to write a SELECT statement, where the tablename is based on the response to a different SELECT query. I can't use stacked queries, and I can only use MySQL.
As pseudo-code, this is what I'd like to do:
tablenamevariable = (SELECT 'tablename');
SELECT * FROM tablenamevariable;
Which should be equivalent to executing SELECT * FROM tablename (where the string tablename comes from the database).
What I have so far is the following, which executes successfully:
SELECT * FROM (SELECT 'tablename') AS x;
However, the result simply prints tablename (which isn't what I want).
The background is an SQL injection which upper-cases all input. So what I want to do is SELECT * FROM (SELECT CHAR([...] USING UTF8MB4)) to be able to select data from a table with lower-case characters in the name.
You can't use a string as an identifier in the same query.
A subquery or an expression can return a string, but not an identifier.
So your subquery like select ... from (select ...) as x doesn't work the way you think. It will not query from the table named by the string. It will query from a derived table which consists of the string value returned by the subquery.
mysql> select * from (select 'abc' as tablename) as x;
+-----------+
| tablename |
+-----------+
| abc |
+-----------+
The reason for this is that in SQL, all identifiers must be fixed at the time the query is parsed, before it evaluates any expressions. This is so the table names can be validated that the corresponding tables exist, and you have SQL privileges to read those tables.
Another reason is that if the subquery worked the way you expect, then there would be no way to simply query strings from a subquery without querying an hypothetical table named by those strings. Also what would you expect it to do if the subquery returned multiple columns or multiple rows?
You clarified in an edit that what you're trying to do is to query a table after your query is formatted with uppercase table names, regardless of how the table was defined.
Case-sensitivity of identifiers in MySQL is a bit complex, because MySQL has versions on different operating systems, some of which have case-sensitive filesystems and some have case-insensitive filesystems.
But the result is that in most cases, it doesn't matter that your table names are uppercase in your query. Table name comparisons are case-insensitive by default on an OS that has uses case-insensitive filesystems.
mysql> select * from mytable limit 1;
+----+-------+
| pk | name |
+----+-------+
| 3 | hello |
+----+-------+
mysql> select * from MYTABLE limit 1;
+----+-------+
| pk | name |
+----+-------+
| 3 | hello |
+----+-------+
mysql> select * from MyTable limit 1;
+----+-------+
| pk | name |
+----+-------+
| 3 | hello |
+----+-------+
(Test performed on MySQL 8.0.31 on MacOS)
On UNIX and Linux, the default is that table comparisons are case-sensitive. But there is an option to configure this if you want it to work in a case-insensitive manner on UNIX or Linux. You should read https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html to understand how this works on different operating systems, and the option you can use to control it.
To do that you would need to use prepared statements:
set #t = 'tablename';
PREPARE stmt FROM concat('select * from ', #n);
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
It is highly unusual that you would need to do that though.

Cannot SELECT table.* because it does not exist, cannot create table because it exists

I have a raspberry pi which has MySQL on it. I´m working on a simple project where I have to only use 1 table. I used INSERT INTO to make an entry into the tickets.
Now I'm trying to use SELECT to see if the data is in, however, SELECT says that the table tickets doesn't exist.
mysql> show tables;
+-------------------+
| Tables_in_tickets |
+-------------------+
| tickets | <-------
+-------------------+
1 row in set (0.00 sec)
As you can see, I drew an arrow pointing at the tickets table, which does exist, then when I try to use SELECT...
mysql> SELECT tickets.*;
ERROR 1051 (42S02): Unknown table 'tickets'
What's the reasoning behind this? Cheers in advance!
Use:
SELECT * FROM tickets
When to use ticket.*
select ticket.* is used to see the content of ticket table when you are joining the ticket table with any other table without alias names. Like:
SELECT tickets.*
FROM tickets join
someOtherTable on tickets.id=someOtherTable.ticketId

Alias Column Names at the Database Level [MySQL]

"Alias" is probably the wrong word, since that's used in the context of referencing column/table names as something else in a Query.
What I'm interested in is if there's a way to give a column two names in the database. If I were to print such a table, it would look like this:
mysql> SELECT * FROM User;
+--------------------------+-----------------+
| id | username | uname | password | pswd |
+----+---------------------+-----------------+
| 0 | bob_jones#gmail.com | some_pw_hash |
| 1 | sue_smith#gmail.com | some_pw_hash |
+--------------------------------------------+
In this case, username and uname would be synonymous in query statements, as would password and pswd.
So the following statements would have the same output:
mysql> SELECT id, username FROM User;
...
mysql> SELECT id, uname FROM User;
...
I would like to avoid having to do something like
mysql> SELECT id, username AS uname FROM User;
So, does a feature like this exist?
Cheers,
Neil
No, this is not possible. To do so, you'd have to add a new, actual second column and use triggers to keep them in sync, which would be silly.
Just write your SQL properly to use the proper column names.
If you don't mind selecting from V_User instead of User, then views can get you what you need.
CREATE VIEW V_User AS
SELECT username as username,
username as uname
FROM User;
Then these 2 queries have the same result:
mysql> SELECT id, username FROM V_User;
...
mysql> SELECT id, uname FROM V_User;
...
As Ken points out, this is not precisely what was asked. But depending on the precise context, it might be just what's needed.

Really strange error on mysql query

I have this query, and I think it talks by itself:
mysql> select id,email from members where email LIKE "%abraham.sustaita#gmail.com%";
+--------+----------------------------+
| id | email |
+--------+----------------------------+
| 272118 | abraham.sustaita#gmail.com |
+--------+----------------------------+
1 row in set (0.69 sec)
mysql> select id,email from members where email = "abraham.sustaita#gmail.com";
Empty set (0.00 sec)
mysql> select id,email from members where id = 272118;
Empty set (0.00 sec)
The data exists, but it returns empty if I use other than LIKE...
When there is such a flagrant impossible sequence of queries, then it's time to think about a table (or index) corruption and to run the Mysql CHECK command.
In that case, running REPAIR TABLE members QUICK did the trick.
If the id is a varchar and the email is a varchar they might have surrounding spaces.

Attaching simple metadata to a MySQL database

Is there a way to attach a piece of metadata to a MySQL database? I'm trying to write code to automatically update the database schema whenever a code upgrade requires it. This requires the storage of a single integer value -- the schema version. I could of course create a whole table for it, but that seems like overkill for just a simple number.
You can use table comments to store the version:
ALTER TABLE table1 COMMENT = '1.4';
You'll have to regex to get the comment from this:
SHOW CREATE TABLE table1;
/COMMENT='(.*)'/
To answer the question as titled, that is for metadata for the entire database and not individual tables, there are a couple of choices, depending on the privileges that you have.
The most direct route is to create a stored function, which requires the CREATE ROUTINE privilege. e.g.
mysql> CREATE FUNCTION `mydb`.DB_VERSION() RETURNS VARCHAR(15)
RETURN '1.2.7.2861';
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT `mydb`.DB_VERSION();
+--------------+
| DB_VERSION() |
+--------------+
| 1.2.7.2861 |
+--------------+
1 row in set (0.06 sec)
If your privileges limit you to only creating tables, you can create a simple table and put the metadata as default values. There’s no need to store any data in the table.
mysql> CREATE TABLE `mydb`.`db_metadata` (
`version` varchar(15) not null default '1.2.7.2861');
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW COLUMNS FROM `mydb`.`db_metadata`;
+---------+-------------+------+-----+------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+------------+-------+
| version | varchar(15) | NO | | 1.2.7.2861 | |
+---------+-------------+------+-----+------------+-------+
1 row in set (0.00 sec)