MySQL varchar column on group_concat shows as text in View - mysql

I have column in base table as acct_num varchar(25) and I am creating a View and GROUP_CONCAT() is set to this column. This is shown as text datatype in show create view. Is it possible to have VARCHAR(25) datatype for GROUP_CONCAT(acct_num) column. Please advise.
What I learnt from MySQL reference:
I though to cast as varchar(25) but CAST can be applied as CHAR not as VARCHAR
There is option to set GLOBAL_SET_GROUP_CONCAT_VALUE = 512 so that you can get output of GROUP_CONCAT() as varchar() - but it didn't work
out for me.

You can set group_concat_max_len to achieve that.
Here is a demo:
SQL:
-- To change the setting globally
set global group_concat_max_len = 512;
-- To change the setting only for current session
set group_concat_max_len = 512;
create table t1(acct_num varchar(25));
create view v1 as select group_concat(acct_num) as gc_acct_num from t1;
desc v1;
Output:
mysql> -- To change the setting globally
mysql> set global group_concat_max_len = 512;
Query OK, 0 rows affected (0.00 sec)
mysql> -- To change the setting only for current session
mysql> set group_concat_max_len = 512;
Query OK, 0 rows affected (0.00 sec)
mysql> create table t1(acct_num varchar(25));
Query OK, 0 rows affected (0.01 sec)
mysql> create view v1 as select group_concat(acct_num) as gc_acct_num from t1;
Query OK, 0 rows affected (0.00 sec)
mysql> desc v1;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| gc_acct_num | varchar(512) | YES | | NULL | |
+-------------+--------------+------+-----+---------+-------+
1 row in set (0.00 sec)

Related

mysql compares accented vs unaccented characters as the same?

This does not make sense to me. Can anyone explain it? I think the column values should be different, so
select * from a1 where f1 = f2;
should find no rows. But...
mysql> create table a1 (f1 varchar(63), f2 varchar(63));
Query OK, 0 rows affected (0.00 sec)
mysql> show create table a1 \G
*************************** 1. row ***************************
Table: a1
Create Table: CREATE TABLE `a1` (
`f1` varchar(63) DEFAULT NULL,
`f2` varchar(63) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql>
mysql> insert into a1 values ('EFBBBFD187D0B5D0BBD0BED0B2D0B5D0BA', 'EFBBBFD187D0B5D0BBD0BED0B2D0B5CC81D0BA');
Query OK, 1 row affected (0.02 sec)
mysql> update a1 set f1 = unhex(f1);
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update a1 set f2 = unhex(f2);
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from a1;
+-------------------+---------------------+
| f1 | f2 |
+-------------------+---------------------+
| человек | челове́к |
+-------------------+---------------------+
1 row in set (0.00 sec)
mysql>
mysql>
mysql> select * from a1 where f1 = f2;
+-------------------+---------------------+
| f1 | f2 |
+-------------------+---------------------+
| человек | челове́к |
+-------------------+---------------------+
1 row in set (0.00 sec)
mysql> select * from a1 where hex(f1) = hex(f2);
Empty set (0.00 sec)
mysql>
The 3 bytes on the beginning, EFBBBF, is "BOM", which indicates that the text is UTF-8-encoded.
The rest look like Cyrillic челове́к, except for the "CC81 -- NSM COMBINING ACUTE ACCENT"
Some collations, including utf8mb4_0900_ai_ci, handle "combining accents", some do not. The "ai" means "accent insensitive".
I would understand this equivalence for a "latin" e. I don't know the rules for a CYRILLIC SMALL LETTER IE, which looks the same е, but is encoded differently.
You might want COLLATE utf8mb4_0900_as_ci, which is "accent sensitive and case insensitive".
Character equivalence is defined by the collation used by the columns in question. A collation defines every pair of characters as equal, less than, or greater than, and this is used for comparisons and for sorting.
Your table uses utf8mb4_0900_ai_ci as the default collation, and this applies to all the columns, since they do not define a collation to override the table's default.
It's pretty common for collations to treat accented characters as equal to their unaccented versions.
If you want to choose a different collation, you may.

How to backfill an auto increment field in MySQL

I have a MySQL Database 5.6.32 connected to SuiteCRM. I am using a plugin that allows for the creation of an auto increment field without any coding.
The challenge I'm having is that I have created this auto increment field after records with data are already in our system. I need to update all previous entries with the auto increment values.
When I create a new record the auto increment field works fine, but I need the unique number for all records as this is being used as a Unique Identifier and the default ID in the system is too long for us to use.
The type of auto increment field it created in the MySQL database is as follows:
# Name Type Collation Null Default
10 customer_number_c varchar(80) utf8_general_ci Yes NULL
This is what I have tried so far to try and populate the field:
UPDATE `suitecrm`.`accounts_cstm` SET `customer_number_c` = auto_increment
The result is:
ERROR #1054 - Unknown column 'AUTO_INCNREMENTAL' in 'Field list'
The field already has a default value of NULL in it as well.
MySQL's builtin auto-increment feature only works with columns of integer data types. Yours is varchar(80). I'm not sure why you did that, but I assume it was deliberate.
You could use a session variable to populate the customer number. As you assign values, it will implicitly cast the integer value of the session variable to the string representation.
SET #num := 0;
UPDATE suitecrm.accounts_cstm
SET customer_number_c = (#num := #num + 1)
ORDER BY ...;
You would have to specify some ORDER BY clause to make sure the increasing values get assigned in the order you want them to be.
But you still won't be able to use AUTO_INCREMENT on the customer_number_c column. So your app must generate new customer number values before inserting new rows to this table.
MySQL will retroactively populate existing rows for you if you add an auto_increment primary key. I just validated this with the following test code:
mysql> create table mytable (name varchar(32)) engine=innodb;
Query OK, 0 rows affected (0.04 sec)
mysql> insert into mytable (name) values ('miles'), ('trane'), ('monk');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from mytable;
+-------+
| name |
+-------+
| miles |
| trane |
| monk |
+-------+
3 rows in set (0.00 sec)
mysql> alter table mytable add column id int unsigned primary key auto_increment first;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select * from mytable;
+----+-------+
| id | name |
+----+-------+
| 1 | miles |
| 2 | trane |
| 3 | monk |
+----+-------+
3 rows in set (0.00 sec)

MySQL decimal field 'Data truncated for column x at row 1' issue

I have a mysql table with a decimal(16,2) field. Seems like the addition operation with another decimal(16,2) field string can cause the Data truncated for column x at row 1 issue, which raises exception in my django project.
I'm aware of multiplication or division operation of that field can cause this issue bacause the result is probably not fit in decimal(16,2) definition, but does the addition and subtraction operation the same?
My MySQL server version is 5.5.37-0ubuntu0.14.04.1. You can reproduce this issue from bellow:
mysql> drop database test;
Query OK, 1 row affected (0.10 sec)
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed
mysql> create table t(price decimal(16,2));
Query OK, 0 rows affected (0.16 sec)
mysql> insert into t values('2004.74');
Query OK, 1 row affected (0.03 sec)
mysql> select * from t;
+---------+
| price |
+---------+
| 2004.74 |
+---------+
1 row in set (0.00 sec)
mysql> update t set price = price + '0.09';
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update t set price = price + '0.09';
Query OK, 1 row affected, 1 warning (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 1
mysql> show warnings;
+-------+------+--------------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------------+
| Note | 1265 | Data truncated for column 'price' at row 1 |
+-------+------+--------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from t;
+---------+
| price |
+---------+
| 2004.92 |
+---------+
1 row in set (0.00 sec)
There are two problems:
You are not storing decimal values, you're trying to store string/varchar, which is converted into double value by mysql, for example following code does not give errors update t set price = price + 0.09; (even executed several times)
Anyway this code gives expected warning (note number) update t set price = price + 0.091; you can change it to update t set price = price + cast(0.091 as decimal(16,2)); of course with cast you can use string values too update t set price = price + cast('0.09' as decimal(16,2));
In my case problem occurs when I try to insert a decimal with 3 digits after the the dot like: 0.xxx on a column defined as DECIMAL(10,2)
I changed it to DECIMAL(10,3) OR used php to enter values like 0.xx on DECIMAL(10,2) table

Confused about comparing date fields with literals

I am puzzled by the behaviour below. Why does the first SELECT statement return 1 while the second statement returns 0? I expect them both to return 1 as the date is greater than or equal to the literal.
Why does collation affect date comparison? When comparing dates against literals, is it wrong to represent the date (or date time) as a string? If so how should I be doing date vs literal comparisons?
mysql> CREATE DATABASE test;
Query OK, 1 row affected (0.00 sec)
mysql> USE test;
mysql> SET NAMES utf8 COLLATE utf8_general_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE foo (
bar date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.15 sec)
mysql> INSERT INTO foo (bar) VALUES ('2013-01-01');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT COUNT(*) FROM foo WHERE bar >= '2013-01-01 00:00:00';
+----------+
| COUNT(*) |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)
mysql> SET NAMES utf8 COLLATE utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT COUNT(*) FROM foo WHERE bar >= '2013-01-01 00:00:00';
+----------+
| COUNT(*) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
Have you tried
SELECT COUNT(*) FROM foo WHERE bar >= _utf8'2013-01-01 00:00:00'
Explanation's here
You probably assume that the db is doing an IMPLICIT type converion of your literal string into a date and comparing the dates. It looks like the db is doing an IMPLICIT type conversion of the date into a string and comparing the strings. The collation affects this conversion and so affects your result.
Try:
SET NAMES utf8 COLLATE utf8_general_ci;
SELECT * FROM foo;
SET NAMES utf8 COLLATE utf8_unicode_ci;
SELECT * FROM foo;
The two queries should give different results that explain the behaviour.
In any case cha's suggestion will work because you are telling the db to EXPLICITLY convert the literal string to a date and then compare the dates.

What happen's to content inside in rows on columns defined as varchar, when illegally reduced length?

Certainly a noobish question, but I got to ask: :-) Assuming a column of type varchar and length 255 and the longest string stored in a row at this column shold have length 200. What happens, if I altered the columns length to less then 200? Would the strings all get "cut"?
By default, it will allow you to alter the column, it will truncate strings longer than the new length, and it will generate a warning.
mysql> create table t (v varchar(20));
Query OK, 0 rows affected (0.06 sec)
mysql> insert into t values ('12345678901234567890');
Query OK, 1 row affected (0.00 sec)
mysql> alter table t modify column v varchar(10);
Query OK, 1 row affected, 1 warning (0.04 sec)
Records: 1 Duplicates: 0 Warnings: 1
mysql> show warnings;
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 'v' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
mysql> select * from t;
+------------+
| v |
+------------+
| 1234567890 |
+------------+
1 row in set (0.00 sec)
If you have the SQL mode STRICT_ALL_TABLES or STRICT_TRANS_TABLES set, the warning becomes an error and the ALTER will fail.
mysql> alter table t modify column v varchar(10);
ERROR 1265 (01000): Data truncated for column 'v' at row 1