MySQL bigint number - different output in SQL and R - mysql

I have stored a value as varchar and as bigint in a MySQL DB:
userID_as_varchar varchar(50) DEFAULT NULL,
userID_as_bigint bigint(20) DEFAULT NULL,
+--------------------+---------------------------+
| userID_as_varchar | userID_as_bigint |
+--------------------+---------------------------+
| 917876131364446205 | 917876131364446200 |
+--------------------+---------------------------+
For any reason, I can't query the full userID_as_bigint value in full precision with SQL, but with R.
Behaviour SQL:
If I query the data or cast it it's always the "rounded" value.
Tested in phpMyAdmin and directly with sql command in shell.
Behaviour R:
If I query the field with R (RMySQL package) the value is complete 917876131364446205
Can anyone explain this behaviour or know a way how to get the full value with SQL.
Best regards.

Not quite sure what you mean, here's a test:
create table test(t1 varchar(50), t2 bigint);
Query OK, 0 rows affected (0.03 sec)
mysql> desc test
-> ;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| t1 | varchar(50) | YES | | NULL | |
| t2 | bigint(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.02 sec)
mysql> insert into test values('917876131364446205', 917876131364446205);
Query OK, 1 row affected (0.01 sec)
mysql> select * from test;
+--------------------+--------------------+
| t1 | t2 |
+--------------------+--------------------+
| 917876131364446205 | 917876131364446205 |
+--------------------+--------------------+
1 row in set (0.00 sec)

Related

MySQL statement with invalid data in WHERE clause returns 0 rows instead of failing

Hopefully this is a simple question. I have the following table:
+---------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| KEY_COL | int(11) | NO | PRI | NULL | |
| COL2 | int(11) | YES | | NULL | |
+---------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)
When I do an update on the table using invalid values in the where clause for KEY_COL, it completes successfully and returns 0 rows affected:
mysql> update LGSRV_TAB_DOC set COL2='9' where KEY_COL='A';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
I have my sql_mode set to STRICT_ALL_TABLES, so I was expecting the update to fail since I'm supplying an invalid value for KEY_COL ('A' instead of a numeric). Is there any way I can change this behavior so that the update fails with an error? I'm running version 8.0.11 on RHEL 6.9.

MARIADB - Can SQL convert NULL to an empty string if no default value is provided?

I have a table that has nullable columns:
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
I insert a row with name set to NULL;
INSERT INTO some_table (id, name) VALUES (1, NULL);
Query OK, 1 row affected (0.02 sec)
SELECT * FROM some_table;
+------+------+
| id | name |
+------+------+
| 1 | NULL |
+------+------+
1 row in set (0.01 sec)
If I alter the table's name column to be not-nullable it apparently converts NULL to an empty string:
ALTER TABLE some_table CHANGE COLUMN name name VARCHAR(255) NOT NULL;
Query OK, 1 row affected, 1 warning (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 1
SELECT * FROM some_table;
+------+------+
| id | name |
+------+------+
| 1 | |
+------+------+
1 row in set (0.02 sec)
At this point I would expect an exception to be raised telling me that I have NULL in my dataset and I can not set the column name to NOT NULL.
Is this a configurable option in SQL/MariaDB?
Why is NULL being converted to an empty string?
There is a warning being invoked when altering the table:
SHOW WARNINGS;
+---------+------+-------------------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------------------+
| Warning | 1265 | Data truncated for column 'name' at row 1 |
+---------+------+-------------------------------------------+
1 row in set (0.01 sec)
Version:
SELECT version();
+----------------+
| version() |
+----------------+
| 5.5.62-MariaDB |
+----------------+
1 row in set (0.02 sec)
Apparently, from the documentation for ALTER TABLE, enabling strict mode would prevent your alter statement from succeeding:
This conversion may result in alteration of data. For example, if you shorten a string column, values may be truncated. To prevent the operation from succeeding if conversions to the new data type would result in loss of data, enable strict SQL mode before using ALTER TABLE.
One way to enable strict mode from within MySQL:
SET GLOBAL sql_mode='STRICT_TRANS_TABLES';
See here for other options.
Using 10.3.15-MariaDB-1 on Debian Buster, I cannot reproduce the problem:
MariaDB [foo]> CREATE TABLE some_table(id int(11), name varchar(255));
Query OK, 0 rows affected (0.009 sec)
MariaDB [foo]> INSERT INTO some_table (id, name) VALUES (1, NULL);
Query OK, 1 row affected (0.003 sec)
MariaDB [foo]> SELECT * FROM some_table;
+------+------+
| id | name |
+------+------+
| 1 | NULL |
+------+------+
1 row in set (0.000 sec)
MariaDB [foo]> ALTER TABLE some_table CHANGE COLUMN name name VARCHAR(255) NOT NULL;
ERROR 1265 (01000): Data truncated for column 'name' at row 1
MariaDB [foo]> SELECT * FROM some_table;
+------+------+
| id | name |
+------+------+
| 1 | NULL |
+------+------+
1 row in set (0.000 sec)
MariaDB [foo]> SELECT version();
+-------------------+
| version() |
+-------------------+
| 10.3.15-MariaDB-1 |
+-------------------+
1 row in set (0.000 sec)
If possible, I suggest you update your MariaDB version. It seems very old to me.

Select from table is slow

My problem is: simple select query takes a long time (3 minutes).
Structure:
mysql> show create table seventhcont_exceptionreport;
seventhcont_exceptionreport | CREATE TABLE `seventhcont_exceptionreport` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`body_html` longtext NOT NULL,
`datetime_created` datetime NOT NULL,
`subject` varchar(256) NOT NULL,
`host` varchar(128) NOT NULL,
`exc_value` varchar(512) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=74607 DEFAULT CHARSET=utf8 |
Rows count:
mysql> select count(*) from seventhcont_exceptionreport;
+----------+
| count(*) |
+----------+
| 7064 |
+----------+
1 row in set (0.00 sec)
Query 1 (normal):
mysql> select id, datetime_created from seventhcont_exceptionreport order by id LIMIT 100 OFFSET 6000;
...
100 rows in set (0.30 sec)
Query 2 (very slow):
mysql> select id, datetime_created from seventhcont_exceptionreport order by id LIMIT 100 OFFSET 7000;
...
63 rows in set (3 min 40.56 sec)
!!! 3 minutes and 40 sec.
Why?
UPDATE
Explain for query 1:
mysql> EXPLAIN select id, datetime_created from seventhcont_exceptionreport order by id LIMIT 100 OFFSET 6000;
+----+-------------+-----------------------------+-------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------------------+-------+---------------+---------+---------+------+------+-------+
| 1 | SIMPLE | seventhcont_exceptionreport | index | NULL | PRIMARY | 4 | NULL | 6100 | |
+----+-------------+-----------------------------+-------+---------------+---------+---------+------+------+-------+
1 row in set (0.00 sec)
Explain for query 2:
mysql> EXPLAIN select id, datetime_created from seventhcont_exceptionreport order by id LIMIT 100 OFFSET 7000;
+----+-------------+-----------------------------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------------------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | seventhcont_exceptionreport | ALL | NULL | NULL | NULL | NULL | 7067 | Using filesort |
+----+-------------+-----------------------------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
UPDATE
Analyze table:
mysql> ANALYZE TABLE seventhcont_exceptionreport;
+--------------------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------------------------+---------+----------+----------+
| 7k.seventhcont_exceptionreport | analyze | status | OK |
+--------------------------------+---------+----------+----------+
1 row in set (2.51 sec)
I am no MySQL specialist, but I might be able to point you in the right direction.
In the first query, we can see in the Explain Plan, that an index access was used. In contrast, for the second query, we can see that a non-index access is performed (type index vs ALL). Also, we can see that MySQL is using Using filesort.
This means MySQL cannot perform the sort operation on the index and is therefore performing it on the data itself. This could be because the sort buffer is too small (also see https://www.percona.com/blog/2009/03/05/what-does-using-filesort-mean-in-mysql/).
Therefore, try to increase the size of your sort buffer (soft_buffer_size).

MySQL INSERT Statement Inserting Too Many Rows

I'm trying to insert a row in a MySQL if a row already exists in the same table with nick in it. Here is the query I'm attempting:
INSERT IGNORE INTO gold_log (nick, amount, stream_online, modification_type, dt)
SELECT DISTINCT nick, 0, 0, 253, DATE_FORMAT(NOW(), '%Y-01-01 00:00:00')
FROM gold_log WHERE nick='PrestonConnors';
I get result:
Query OK, 2243 rows affected, 2 warnings (0.24 sec)
Records: 2243 Duplicates: 0 Warnings: 2
When I run the SELECT statement independently it only returns one result (which is what I expect):
mysql> SELECT DISTINCT nick, 0, 0, 253, DATE_FORMAT(NOW(), '%Y-01-01 00:00:00') FROM gold_log WHERE nick='PrestonConnors';
+----------------+---+---+-----+-----------------------------------------+
| nick | 0 | 0 | 253 | DATE_FORMAT(NOW(), '%Y-01-01 00:00:00') |
+----------------+---+---+-----+-----------------------------------------+
| PrestonConnors | 0 | 0 | 253 | 2015-01-01 00:00:00 |
+----------------+---+---+-----+-----------------------------------------+
1 row in set (0.01 sec)
Can someone help form my INSERT IGNORE INTO statement into one that will only INSERT one row into the table and also explain what was wrong with my query?
Here is the layout of the table:
mysql> describe gold_log;
+-------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| nick | char(25) | NO | PRI | NULL | |
| amount | decimal(10,4) | YES | MUL | NULL | |
| stream_online | tinyint(1) | NO | MUL | NULL | |
| modification_type | tinyint(3) unsigned | NO | MUL | NULL | |
| dt | datetime | NO | PRI | NULL | |
+-------------------+---------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
And here are the warnings:
mysql> SHOW warnings;
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1592 | Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT IGNORE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave. |
| Note | 1592 | Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave. |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
Simply, It is a bug in MySQL (I found it in mysql5.5.16); but when I update to (5.6.24):
mysql> status
--------------
D:\xampp\mysql\bin\mysql.exe Ver 14.14 Distrib 5.6.24, for Win32 (x86)
It works properly.
See:
http://bugs.mysql.com/bug.php?id=58637
http://bugs.mysql.com/bug.php?id=72921

MySql: Tinyint (2) vs tinyint(1) - what is the difference?

I knew boolean in mysql as tinyint (1).
Today I see a table with defined an integer like tinyint(2), and also others like int(4), int(6) ...
What does the size means in field of type integer and tinyint ?
The (m) indicates the column display width; applications such as the MySQL client make use of this when showing the query results.
For example:
| v | a | b | c |
+-----+-----+-----+-----+
| 1 | 1 | 1 | 1 |
| 10 | 10 | 10 | 10 |
| 100 | 100 | 100 | 100 |
Here a, b and c are using TINYINT(1), TINYINT(2) and TINYINT(3) respectively. As you can see, it pads the values on the left side using the display width.
It's important to note that it does not affect the accepted range of values for that particular type, i.e. TINYINT(1) still accepts [-128 .. 127].
It means display width
Whether you use tinyint(1) or tinyint(2), it does not make any difference.
I always use tinyint(1) and int(11), I used several mysql clients (navicat, sequel pro).
It does not mean anything AT ALL! I ran a test, all above clients or even the command-line client seems to ignore this.
But, display width is most important if you are using ZEROFILL option, for example your table has following 2 columns:
A tinyint(2) zerofill
B tinyint(4) zerofill
both columns has the value of 1, output for column A would be 01 and 0001 for B, as seen in screenshot below :)
mysql> CREATE TABLE tin3(id int PRIMARY KEY,val TINYINT(10) ZEROFILL);
Query OK, 0 rows affected (0.04 sec)
mysql> INSERT INTO tin3 VALUES(1,12),(2,7),(4,101);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM tin3;
+----+------------+
| id | val |
+----+------------+
| 1 | 0000000012 |
| 2 | 0000000007 |
| 4 | 0000000101 |
+----+------------+
3 rows in set (0.00 sec)
mysql>
mysql> SELECT LENGTH(val) FROM tin3 WHERE id=2;
+-------------+
| LENGTH(val) |
+-------------+
| 10 |
+-------------+
1 row in set (0.01 sec)
mysql> SELECT val+1 FROM tin3 WHERE id=2;
+-------+
| val+1 |
+-------+
| 8 |
+-------+
1 row in set (0.00 sec)
About the INT, TINYINT... These are different data types, INT is 4-byte number, TINYINT is 1-byte number. More information here - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT.
The syntax of TINYINT data type is TINYINT(M), where M indicates the maximum display width (used only if your MySQL client supports it).
Numeric Type Attributes.