I am trying to select items in MySQL with consideration for case sensitivity, but I am having issues getting MySQL to perform any case distinction.
For example, all of the following statements
mysql> SELECT * FROM mytable WHERE name="alpha";
mysql> SELECT * FROM mytable WHERE name="ALPHA";
mysql> SELECT * FROM mytable WHERE name="aLpHa";
return the same results:
+----+-------+
| id | name |
+----+-------+
| 1 | alpha |
+----+-------+
1 row in set (0.00 sec)
I recognize that some character sets and collations in MySQL do not distinguish between case, and so changing the character set and collation from the default is a necessary step. I have tried changing and converting the table's character set and collate to utf8 and utf8_unicode_ci respectively, but I am uncertain if it worked correctly.
mysql> SHOW TABLE STATUS;
+---------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+---------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| mytable | InnoDB | 10 | Compact | 68886 | 83 | 5783552 | 0 | 7372800 | 17825792 | 67039 | 2014-08-02 15:05:07 | NULL | NULL | utf8_unicode_ci | NULL | | |
+---------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
1 row in set (0.04 sec)
mysql> SHOW FULL COLUMNS FROM mytable;
+-------+-------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+-------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| id | int(11) | NULL | NO | PRI | NULL | auto_increment | select,insert,update,references | |
| name | varchar(10) | utf8_unicode_ci | NO | | NULL | | select,insert,update,references | |
+-------+-------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
2 rows in set (0.01 sec)
As you can see from above, the collation of the table has now been changed to utf8_unicode_ci and the collation of the relevant column has been changed as well.
Is there any additional step I need to perform so that MySQL will make a distinction with respect to character case? I am using MySQL Server version: 5.5.37-0ubuntu0.13.10.1 (Ubuntu).
Note that I cannot simply use queries with the BINARY keyword, such as:
SELECT * FROM mytable WHERE BINARY name="alpha";
because I am actually just using MySQL through Django's ORM, which does not support this type of lookup as far as I know. Thank you in advance for your help!
You can use option:
COLLATE utf8_bin
Example:
http://sqlfiddle.com/#!2/60d73/1/0
vs.
http://sqlfiddle.com/#!2/60d73/2/0
You can alter your table using:
alter table mytable ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
Related
I have table ip_per_nat_vlan, innodb format. When I give truncate table, table is empty.
Then I have php script, which fill data into this table.
When is this script finished without errors (simple insert statemets) situation is following:
select * from ip_per_nat_vlan;
Empty set (0.00 sec)
.
select count(*) from ip_per_nat_vlan;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
.
show table status;
+----------------------------------+--------+---------+------------+----------+----------------+-------------+-----------------+--------------+------------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+----------------------------------+--------+---------+------------+----------+----------------+-------------+-----------------+--------------+------------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| ip_per_nat_vlan | InnoDB | 10 | Dynamic | 141291 | 100 | 14172160 | 0 | 6832128 | 25165824 | 143563 | 2017-12-24 16:26:40 | 2018-06-13 09:01:33 | NULL | utf8_unicode_ci | NULL |
MySQL says, that there should be 14172160 rows, but I dont see any. Where could be a problem? Transactions? But I dont see any running thread and no any fault.
Thank you. D
Structure of table is:
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ipAddress | varchar(255) | NO | UNI | NULL | |
| nat | int(11) | NO | | NULL | |
| vlan | int(11) | NO | | NULL | |
| district | varchar(255) | YES | | NULL | |
| idOblasti | int(11) | YES | | NULL | |
| type | varchar(255) | NO | | NULL | |
| macAddress | varchar(255) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
There are various ways to "count" rows in a table.
The normal way. Just count them.
select count(*) as table_rows from table_name ;
Accuracy: 100% accurate count at the time of the query is run.
using the information_schema tables
select table_rows
from information_schema.tables
where table_schema = 'database_name'
and table_name = 'table_name' ;
Accuracy: Only an approximation. If the table is the target of frequent inserts and deletes, the result can be way off the actual count. This can be improved by running ANALYZE TABLE more often.
Efficiency: Very good, it doesn't touch the table at all.
As count option is 100% accurate, your table doesn't contain any data.
Check your code and default commit option of MySQL.
Looks like you are inserting rows, but not committing them, check your index length.
Check more details here
https://dba.stackexchange.com/questions/151769/mysql-difference-between-using-count-and-information-schema-tables-for-coun
First thing, I am not sure how mysql run this line and produce the result
select count() from ip_per_nat_vlan
count() will return [Err] 1064.
count(*) or else a field name should be mentioned inside.
I have the following MySQL table:
| customers | CREATE TABLE `customers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
COLLATE=utf8_unicode_ci |
The table already has two rows:
+----+-----------+
| id | name |
+----+-----------+
| 1 | John Woo |
| 3 | Maria Loo |
+----+-----------+
2 rows in set (0.00 sec)
I am trying to alter the table with the following statement:
alter table customers add column (identity varchar(32) not null);
I would expect this statement to fail, due to the fact that I do not specify a default value and the table already has some rows. But it does not. Instead, it adds the column and sets '' as value for that new
column to all existing rows.
+----+-----------+----------+
| id | name | identity |
+----+-----------+----------+
| 1 | John Woo | |
| 3 | Maria Loo | |
+----+-----------+----------+
2 rows in set (0.00 sec)
Is there a way I can make MySQL behave as I expect? I think there is something that one can set at MySQL server configuration variables. But I am not sure.
Any help?
Update Note that strict mode is already ON:
mysql> show variables where variable_name like '%mode%';
+--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------------------------------------------------------------------------------------------- ---------------------+
| block_encryption_mode | aes-128-ecb |
| gtid_mode | OFF |
| innodb_autoinc_lock_mode | 1 |
| innodb_strict_mode | ON |
| offline_mode | OFF |
| pseudo_slave_mode | OFF |
| rbr_exec_mode | STRICT |
| slave_exec_mode | STRICT |
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
9 rows in set (0.00 sec)
The reason appears to be that strict mode is enforced for DML issued to the database. DDL does not go through the DML machinery. Why does it behave this way? Speculation- if the database owner wants a column to be not null, then the database is doing its best to adhere to the owner's intent, which it can do with the implicit defaults feature, if the owner does not provide an explicit default.
See this answer for a reference to a sqlfiddle proof:
MySQL add a NOT NULL column
I have a mysql table named t_media_items. I have index on 3 cols (parent_id, type, weight). The index size is 2.52MB.
mysql> show indexes from t_media_items;
+---------------+------------+--------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+--------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t_media_items | 0 | PRIMARY | 1 | id | A | 113779 | NULL | NULL | | BTREE | | |
| t_media_items | 1 | idx_ptw | 1 | parent_id | A | 16254 | NULL | NULL | | BTREE | | |
| t_media_items | 1 | idx_ptw | 2 | type | A | 16254 | NULL | NULL | | BTREE | | |
| t_media_items | 1 | idx_ptw | 3 | weight | A | 113779 | NULL | NULL | | BTREE | | |
+---------------+------------+--------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.01 sec)
mysql> SELECT table_name AS "Tables", round(((index_length) / 1024 / 1024), 2) SIB
FROM information_schema.TABLES
WHERE table_schema = "XXXX" and table_name='t_media_items'
ORDER BY (index_length ) DESC;
+---------------+------+
| Tables | SIB |
+---------------+------+
| t_media_items | 2.52 |
+---------------+------+
1 row in set (0.00 sec)
I tried to alter length on another column, name "rand_key". The strange issue is after columned alter, the INDEX size suddenly increase to 5.52MB, even the "rand_key" is not part of the index.
mysql> ALTER TABLE `t_media_items` CHANGE `rand_key` `rand_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
Query OK, 108503 rows affected (7.24 sec)
Records: 108503 Duplicates: 0 Warnings: 0
Here is INDEX_LENGTH after ALTER
mysql> SELECT table_name AS "Tables", round(((index_length) / 1024 / 1024), 2) SIB
FROM information_schema.TABLES
WHERE table_schema = "tallcat" and table_name='t_media_items'
ORDER BY (index_length ) DESC;
+---------------+------+
| Tables | SIB |
+---------------+------+
| t_media_items | 5.52 |
+---------------+------+
1 row in set (0.00 sec)
Could anyone help me explain the issue? Thank you
ALTER TABLE performs a table restructure, which is make an empty clone of the table, apply the alter, and copy data to it. Indexes are rebuild as a by-product of this process.
But as it builds the index incrementally while filling the table with data, it doesn't take advantage of fast index creation. The indexes are stored less compactly.
I can't tell if this explains the more than 2x increase in size, but it's possible.
I'm assuming that you're using MySQL 5.5 or later, or 5.1 with the InnoDB plugin. Earlier versions do not support fast index creation anyway.
Our developers frequently forget to specify that nulls are allowed when adding columns to existing tables. MySQL defaults to not allowing nulls if Null is not included when using the Alter Table command to add a column
Is there a way to configure MySQL so that new columns allow nulls unless Not Null is explicitly included with the alter table command?
We use PHPMyAdmin to alter tables so a method of making all newly added fields allow nulls through PHPMyAdmin would work.
MySQL's default behavior is allowing nulls by default on alter table commands. It probably has something to do with PHPMyAdmin.
mysql> desc foo;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| client_id | int(11) | YES | | NULL | |
| item_id | int(11) | YES | | NULL | |
+-----------+---------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> alter table foo add (a char(1));
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc foo;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| client_id | int(11) | YES | | NULL | |
| item_id | int(11) | YES | | NULL | |
| a | char(1) | YES | | NULL | |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)
You can specify the DEFAULT NULL when creating the new column like:
ALTER TABLE table
ADD COLUMN column VARCHAR(255) DEFAULT NULL;
I have a table I want to bea ble to do fulltext searches on, but I can't seem to get any hits on my search terms.
Here's what my table looks like (I took out a few columns that I am confident are not important):
mysql> SHOW TABLE STATUS LIKE 'transcripts';
+-------------+--------+---------+------------+-------------------+----------+----------------+
| Name | Engine | Version | Row_format | Collation | Checksum | Create_options |
+-------------+--------+---------+------------+-------------------+----------+----------------+
| transcripts | MyISAM | 10 | Dynamic | latin1_swedish_ci | NULL | |
+-------------+--------+---------+------------+-------------------+----------+----------------+
mysql> DESCRIBE transcripts;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| content | text | YES | | NULL | |
| raw_content | text | YES | MUL | NULL | |
| tape_id | int(11) | YES | | NULL | |
| state | int(11) | YES | | 0 | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+-------------+----------+------+-----+---------+----------------+
mysql> SHOW INDEXES FROM transcripts;
+-------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type |
+-------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
| transcripts | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE |
| transcripts | 1 | raw_content_index | 1 | raw_content | NULL | NULL | NULL | NULL | YES | FULLTEXT |
+-------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
Proof that there is a row to find:
mysql> SELECT id, raw_content FROM transcripts;
+----+-------------+
| id | raw_content |
+----+-------------+
| 1 | foo |
+----+-------------+
And here are my flailing attempts to get the search to work:
mysql> SELECT * FROM transcripts WHERE MATCH(raw_content) AGAINST ('foo');
Empty set (0.00 sec)
mysql> SELECT * FROM transcripts WHERE MATCH(raw_content) AGAINST ('foo' IN BOOLEAN MODE);
Empty set (0.00 sec)
mysql> SELECT id FROM transcripts WHERE MATCH(raw_content) AGAINST ('foo' IN NATURAL LANGUAGE MODE);
Empty set (0.00 sec)
mysql> SELECT * FROM transcripts WHERE MATCH(raw_content) AGAINST ('+foo*' IN BOOLEAN MODE);
Empty set (0.00 sec)
What am I doing wrong?
by default fulltext ignores words with 3 or less characters
(now posted as an answer by request :) )
Here is something else to consider:
You can not only change the default length, but you can also change the stopword list. You may want to change the stop words because MySQL will not index this list of 543 words.
Try creating your own stopword list and changing the min word length.
Step 1) Create a stop word list of your own. You could add 'a','an', and 'the'.
echo "a" > /var/lib/mysql/custom_stopwords.txt
echo "an" >> /var/lib/mysql/custom_stopwords.txt
echo "the" >> /var/lib/mysql/custom_stopwords.txt
Step 2) Add these options to /etc/my.cnf
ft_min_word_len=2
ft_stopword_file=/var/lib/mysql/custom_stopwords.txt
Step 3) service mysql restart
Step 4) Create new FULLTEXT indexes. Any existing FULLTEXT indexes before restart of mysql should be reindexed.
Give it a Try !!!