Mysql: Generate error on overflow-warning - mysql

In MySQL, an overflow creates only a warning and MySQL destroys the data you feed it:
mysql> create table tmp(data tinyint primary key);
Query OK, 0 rows affected (7.83 sec)
mysql> insert into tmp set data = 200;
Query OK, 1 row affected, 1 warning (2.27 sec)
mysql> select * from tmp;
+------+
| data |
+------+
| 127 |
+------+
1 row in set (0.00 sec)
This is a huge problem, especially when using MySQL via a programming language, where one (usually) does not check any MySQL-warnings. This may cause not only data-corruption, but data-corruption that is hidden and may remain undetected - one of the worst things that may happen in a database.
Is there a way to configure MySQL so that an overflow causes an ERROR (similar to a syntax error) and not only a warning?

See Mysql documentation
you have to activate the strict SQL mode:
If strict SQL mode is enabled, MySQL rejects the out-of-range value with an error, and the insert fails, in accordance with the SQL standard.
If no restrictive modes are enabled, MySQL clips the value to the appropriate endpoint of the range and stores the resulting value instead.

Related

Hashbytes equivalent in MySQL

I am moving my data from SQL Server to MySQL. The data is moving without any issues, but I am trying to come up with a way to validate the integrity of the data between SQL Server and MySQL. I am having issues with regards datatypes VARCHAR and NVARCHAR. Since these are ranging from 255 to MAX. I am trying to do hash comparison between these datatypes but they are not matching.
For testing purpose I tried this:
mysql> SET #test := repeat('t',50000);
Query OK, 0 rows affected (0.00 sec)
mysql> select md5(#test);
+----------------------------------+
| md5(#test) |
+----------------------------------+
| a9cf60d59fe2fb94a84bc106eca028be |
+----------------------------------+
1 row in set (0.01 sec)
Trying the same in SQL Server gives something different:
DECLARE #Test NVARCHAR(MAX) = REPLICATE(CONVERT(NVARCHAR(MAX), N't'), 50000);
SELECT HashBytes('MD5', CONVERT(varchar, #Test));
0x3C48C287BC783516AC89297848A104FE
select LOWER(CONVERT(VARCHAR(32), HashBytes('MD5', CONVERT(varchar, #Test)), 2));
3c48c287bc783516ac89297848a104fe
SELECT CONVERT(VARCHAR(32),HashBytes('MD5', #Test),2);
40752EB301B41EEAEB309348CE9711D6
As you can see none of the output in SQL Server is not matching with MySQL. Hence, looking for some guidance here as to how can I do this data comparison.
One page as a unit of data storage for sql server database file is only 8KB and the limit for varchar LEN is 8000, so following your test example, you won't be able to get the hex result of 50000 characters per page. Instead, it is the result of your #Test example that is calculated on a string length of 8000 characters.

MySql WorkBench AES 256 Decryption

I have table with:
1) Encrypted_ID varchar (256)
2) Initialization Vector(iv)varchar(256).
I would like to decrypt the column value using the key
I am using:
select Cast(AES_DECRYPT(Encrypted_ID,'Key',InitializationVector_iv)as CHAR ) as DecryptedValue from MyTable;
The result is Null.
I Also tried:
select Cast(AES_DECRYPT(AES_ENCRYPT(Encrypted_ID,'Key',InitializationVector_iv),'Key') as CHAR ) as DecryptedValue from MyTable;
The result is blob for few rows.
I'm not sure what I'm doing wrong here. Can any one help with the syntax to decrypt the column when I have:
Key
Initialization Vector value
Encrypted Column
There's actually nothing wrong with your first query, syntactically it's spot on as this worked example demonstrates.
mysql> SET ##SESSION.block_encryption_mode = 'aes-256-cbc';
mysql> create table MyTable(
-> Encrypted_ID varbinary(256),
-> InitializationVector_iv varbinary(16)
-> );
Query OK, 0 rows affected (0.93 sec)
mysql> SET #iv = RANDOM_BYTES(16);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO MyTable SET Encrypted_ID = AES_ENCRYPT('hello','key', #iv), InitializationVector_iv = #iv;
Query OK, 1 row affected (0.17 sec)
mysql> SELECT CAST(AES_DECRYPT(Encrypted_ID,'key', InitializationVector_iv) AS CHAR) from MyTable;
+------------------------------------------------------------------------+
| CAST(AES_DECRYPT(Encrypted_ID,'key', InitializationVector_iv) AS CHAR) |
+------------------------------------------------------------------------+
| hello |
+------------------------------------------------------------------------+
1 row in set (0.00 sec)
As for why it's not working, I managed to get the query to return NULL in 2 scenarios. One, you get NULL returned if you use a different iv for encryption and decryption, so you might want to look at how you are storing as the iv. Two, you get NULL where you have the block_encryption_mode variable set differently when storing and trying to retrieve the value, check that you're not accidentally reverting to the default 'aes-128-ebc between sessions. There may be others...
The second query will fail because you need to supply the iv to both of he encryption and decryption functions, you only use it to encrypt. Also, since you are taking the values from the MyTable, Encrypted_ID will already be encrypted and the effect of this query would be to encrypt it again, before reversing that to get you back to the stored (encrypted) value.
Finally, AES is only going to use 16 bytes of the iv so you might as well make that VARBINARY(16).
AES doesn't work with MySQL Workbench in my case.
I have to use the mysql console.
MySql Workbench worked for me.
In my Case, encrypted value was encoded in base 64.
So I had to decode base 64 value and IV Using "From_base64" function.
SET block_encryption_mode = 'aes-256-cbc';
set #k = 'Key';
set #iv = From_base64('InitializationVector');
set #v = from_base64('EncryptedValue');
select CAST(AES_DECRYPT(#v, #k, #iv) AS CHAR);
Please make sure the encryption type, base 64 encoding, Hex/Unhex of the values/Iv are correct before you start working on the decryption.
Review MYSql functions
https://dev.mysql.com/doc/refman/8.0/en/string-functions.html
Hope this helps for someone.

create database if not exists dbname , 1 row affected

When I try to create a database which already exists,
CREATE DATABASE IF NOT EXISTS test;
Query OK, 1 row affected (0.00 sec)
CREATE DATABASE IF NOT EXISTS test;
Query OK, 1 row affected, 1 warning (0.00 sec)
Why does it show 1 row affected message second time , even though it is not creating a new database with the same name?
Although the CREATE DATABASE IF NOT EXISTS test; command won't directly modify rows in an exiting instance of the test database, it will affect the actual details stored internally in the mysql database, or possibly in one of the derived meta views, like the information_schema or performance_schema etc.
The reported Query OK, 1 row affected (0.00 sec) is referring to a row in one of these internal data constructs. When you reissue the CREATE DATABASE command, and it fails gracefully thanks to the IF NOT EXISTS clause, it is still likely to store meta-data internally, maybe an accumulating field that counts warnings or similar, or even just a 'last acted on' timestamp against this database's row. In any case the stored data in this record is changed, and is reflected as an 'affected' row.

MySQL row_count() function always returning 0

I want to show the result of rows affected after update, insert, or delete in mysql. I have put
DELETE FROM A WHERE ID='1';
SELECT ROW_COUNT();
With the ROW_COUNT the last statement, but the result show me is 0.
If you want to know number of rows affected by delete query in PHPMYADMIN then by running your query it will show you the result see below screenshot :
As #Flash Thunder said PHPmyadmin does not allow multiple queries sent at once
If you want to see the affected rows then you can also write a script using PHP which will exceute you sql query and returns the number of affected rows
Just to be clear.
phpMyAdmin is written in PHP, and PHP does not allow multiple queries sent at once... if you are sending two queries separately, second query is on new connection, so it has no access to previous query information. That's why SELECT ROW_COUNT(); returns 0.
But by default phpMyAdmin returns affected rows count in information after query. It probably uses mysql(i)_affected_rows() function.
FOUND_ROWS() returns number of tables in database when there was no previous query.
mysql> use hunting;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select found_rows();
+--------------+
| found_rows() |
+--------------+
| 24 |
+--------------+
1 row in set (0.00 sec)
mysql> show tables;
(...)
24 rows in set (0.00 sec)

How to perform MySQL spatial buffer function successfully?

Does anyone ever use MySQL spatial buffer function successfully?
I've read the documentation here: http://dev.mysql.com/doc/refman/5.0/en/functions-that-create-new-geometries-from-existing-ones.html#function_buffer
As stated in the documentation, buffer function has 2 parameters. The first one is geometry typed, the second one is distance.
I've try to make a geometry variable
mysql> set #g1 = geomfromtext('POINT(1 1)');
Query OK, 0 rows affected (0.00 sec)
Then, to ensure that my variable is correctly set, I perform a query. If the variable not correctly set, such a query will return NULL. In this case, it is confirmed that my variable is correctly set
mysql> select astext(#g1);
+-------------+
| astext(#g1) |
+-------------+
| POINT(1 1) |
+-------------+
1 row in set (0.00 sec)
I run a query to select a buffer as stated in documentation
mysql> select astext(buffer(#g1, 5));
ERROR 1305 (42000): FUNCTION module_devel.buffer does not exist
Do I miss something here?
EDIT Sorry guys, I think I miss this:
12.17.5.3.2. Spatial Operators
OpenGIS proposes a number of other functions that can produce
geometries. They are designed to implement spatial operators.
These functions are not implemented in MySQL.
This is related to this bug report maybe. Which MySQL server are you using? Maybe you should upgrade to 5.6.