MySQL SELECT against varbinary column - mysql

This is a follow up to a previous issue I had posted here.
I created a test table:
CREATE TABLE `my_test_table` (
`record_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`col1` BINARY(20) NULL DEFAULT NULL,
`col2` CHAR(40) NULL DEFAULT NULL,
PRIMARY KEY (`record_id`)
)
Then ran the statement:
INSERT INTO my_test_table (col1, col2) VALUES(sha1('test'), sha1('test') );
The data looks like...
1 0x6139346138666535636362313962613631633463 a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
I'm not sure how I can select against the VARBINARY column. I can select against the CHAR like:
SELECT * FROM my_test_table WHERE col2 = sha1('test');
I've tried
SELECT * FROM my_test_table WHERE col1 = hex(sha1('test'));
And other variations but can't seem to find a solution (if there is one). I need to be able to check to see if a value already exists in the database before I allow a new insert. I was looking at VARBINARY and BINARY based on previous suggestions. Thanks.

I have not read your previous question, but based on the source code in this question, you are only storing the first 20 characters of the sha1 hash in col1, so if you want to select it you should just look for the first 20 characters of the sha1 hash.
For example:
SELECT *
FROM my_test_table
WHERE col1 = left(sha1('test'),20);

Data truncation: Data too long for column 'col1' at row 1: INSERT INTO my_test_table (col1, col2) VALUES(sha1('test'), sha1('test') )
Can this be the reason why you cannot select the data properly?

BTW the sha1('test') returns a STRING of hex characters...
You should use unhex(sha1('test')) when inputing data as a hex string, or else it wont be entered as acsii values which wont work with matching at all
SELECT * FROM my_test_table WHERE col1 = unhex(sha1('test'));
should be the matching query also.

Related

MySQL SELECT row based on prefix

Im attempting to do a SELECT on data in a table that contains prefixes, and I have the "keyword".
So unlike a normal search where the prefix/keyword is contained in the row data, and that the prefix/keyword is shorter (or contained in) a possible row of data.
This is the opposite. If have prefixes in rows and I want to find the best matching row based on the (longer) word/phase.
CREATE TABLE table1 (id INT NOT NULL AUTO_INCREMENT, keyCode VARCHAR(45) NULL, Username VARCHAR(45) NULL, PRIMARY KEY (id));
INSERT INTO table1(keyCode,Username)VALUES('123','Peter')
INSERT INTO table1(keyCode,Username)VALUES('456','Paul')
INSERT INTO table1(keyCode,Username)VALUES('1234','John')
Now let's say the phrase I have been given is longer than the prefix in the data.
Like this:
SELECT * FROM table1 WHERE keyCode LIKE '123456%';
I know this will not work, but I would like to return the Row with User 'John'.
How?
(I can use stored procedures)
You may phrase your LIKE expression in the reverse order:
SELECT *
FROM table1
WHERE '123456' LIKE CONCAT(keyCode, '%');
This would compare, for example, '123456' against '1234%', which should be a match in this case.
You can check for the existence of the keyCode prefix at the beginning of your string using LOCATE(). For example:
SELECT *
FROM table1
WHERE LOCATE(keyCode,'123456') = 1;

how to make default text column where comparision binary (case sensitive and trim)

Sorry if this is duplicated, but I don't know how to find about the question.
Hi, this my table:
CREATE TABLE `log_Valor` (
`idLog_Valor` int(11) NOT NULL AUTO_INCREMENT,
`Valor` text binary NOT NULL,
PRIMARY KEY (`idLog_Valor`)
)
ENGINE=InnoDB;
INSERT INTO `log_Valor` (Valor) VALUES ('teste');
INSERT INTO `log_Valor` (Valor) VALUES ('teste ');
I have 2 rows:
1 | 'teste'
2 | 'teste '
When I run:
SELECT * FROM log_Valor where valor = 'teste'
It returns the two rows.
How do I make default comparison case sensitive and to not trim without having to specify in the query BINARY?
Use LIKE instead of =.
SELECT * FROM log_Valor WHERE valor LIKE 'teste';
From the documentation
In particular, trailing spaces are significant, which is not true for CHAR or VARCHAR comparisons performed with the = operator
DEMO

MySQL, Search for data containing hex character

I've got a table my_table with a varchar column col1. utf8
If I was looking for all rows containing the letter a in col1 (balloon, aardvark, etc) then I'd do:
select col1
from my_table
where col1 like "%a%" -- But how search for special hex character?
But what should I put instead of "%a%" if I'm looking for a special hex character, in this case 0xFFFC?
(This is the character: http://www.fileformat.info/info/unicode/char/fffc/index.htm)
Note that I am looking for a way to specify this character in the WHERE clause. I've seen this https://dev.mysql.com/doc/refman/5.7/en/hexadecimal-literals.html as well as Stackoverflow questions/answers that also use hex characters in the Select part. I need it in the WHERE clause. I have seen this How to find certain Hex values and Char() Values in a MySQL SELECT but that uses char(128), but I haven't got an equivalent char number in my case.
use: 0x61 == 'a'
select col1
from my_table
where col1 LIKE concat('%',0x61,'%');
Her is a Sample
CREATE TABLE `tmptable` (
`image` varchar(250) DEFAULT NULL,
UNIQUE KEY `d` (`image`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tmptable` (`image`)
VALUES
('äöüß');
> SELECT image,hex(image) FROM tmptable WHERE image LIKE concat ('%',0xC39F,'%');
+--------------+--------------------------+
| image | hex(image) |
+--------------+--------------------------+
| äöüß`´' | C3A4C3B6C3BCC39F60C2B427 |
+--------------+--------------------------+
1 row in set (0.00 sec)
You can write your 'select' as this:
select col1
from my_table
where col1 LIKE CONCAT('%',X'FFFC','%');
You can read how use hexadecimal, as you say, in documentation https://dev.mysql.com/doc/refman/5.7/en/hexadecimal-literals.html
and using concat you use the character resolved.

Mysql match against numeric keyword

I use mysql full-text index.
I found it can not matches a key numeric word as '1' in '1,2,3' or '1 2 3'.
I use this query "SELECT * FROM users u where match(u.leader_uids) against('1' IN BOOLEAN MODE);"
How to solve this issue?
Thanks a lot!
I am Providing the example hope it will works for you i think
MATCH (field) AGAINST ('+856049' IN BOOLEAN MODE)
It will work only with words of 4 or more digits. So you must concat some prefix in the leader_uid before saving it. Example:
CREATE TABLE mytable(
id INT NOT NULL KEY AUTO_INCREMENT,
myfield TEXT,
FULLTEXT KEY ix_mytable (myfield)
);
INSERT INTO mytable (myfield) VALUES
('id_1 id_2 id_3'),
('id_8'),
('id_4 id_1');
SELECT * FROM mytable
WHERE MATCH(myfield) AGAINST ('+id_1' IN BOOLEAN MODE);
-- will select rows 1 and 3
You can change the minimum amount of chars required for the words, in mysql config:
https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_ft_min_token_size

Strict matching of strings and integers

I am writing a flexible search mechanism for a customer's website. I am utilizing union clauses to query a number of different fields in the database in search of a string value entered by the user. This works fine except for one issue.
When comparing a string of a text to an integer that is currently set to zero, the match always returns true. In other words, according to MySQL, "email#example.com" is equal to 0.
I have tried utilizing the CAST and CONVERT function to turn this into a standard string to string comparison, but I can't seem to get the syntax right. My attempts either repeat the above issue or return no rows at all when some should match. I am also concerned that doing this would have an effect on performance since I am combining lots of unions.
What I really need is a strict comparison between an entered string and the value in the database, be it an integer or string.
EDIT:
Here is an example.
CREATE TABLE `test_table` (
`id` INT NOT NULL AUTO_INCREMENT ,
`email` VARCHAR(255) NOT NULL ,
`phone` BIGINT(19) NOT NULL DEFAULT '0' ,
PRIMARY KEY (`id`) )
ENGINE = MyISAM;
INSERT INTO `test_table` (`id`, `email`, `phone`) VALUES (1, 'email#example.com', 0);
SELECT * FROM test_table WHERE phone = 'email#example.com';
Execute this and the one row that has been inserted will return. My issue is that it shouldn't!
This query should fail:
SELECT * FROM test_table WHERE cast(phone as char) = 'email#example.com';
The cause of the original problem is that when comparing strings and numbers, it converts the string to a number (so you can write where phone = '123'). You need to use an explicit cast of the field to make it a string-to-string comparison, to prevent this default conversion.
Unfortunately, casting like this is likely to prevent it from using indexes. Even if the field is already char, the cast apparently prevents it from indexing.
You could also solve it during input validation: if phone is an integer, don't allow the user to provide a non-integer value in the search field.
How about replacing:
SELECT * FROM test_table WHERE phone = 'email#example.com'
with:
SELECT * FROM test_table WHERE phone = 'email#example.com' and phone <> 0
<> means different from.
This will work for you because you are using 0 in the phone column to mean there isn't a phone number (although it would be better style to use NULL for no phone number).