簡單說一下MySQL的varchar排序問題,引以為戒。
示例表結構:
先來看一下,我的表結構
代碼如下 復制代碼
show create table cardserver G
*************************** 1. row ***************************
Table: cardserver
Create Table: CREATE TABLE `cardserver` (
`id` int(11) NOT NULL default '0',
`ver` int(11) default NULL,
`createtime` datetime default NULL,
`updatetime` datetime default NULL,
`game_id` int(2) NOT NULL default '0',
`server_id` varchar(2) NOT NULL default '',
`server_name` varchar(40) NOT NULL default '',
PRIMARY KEY (`id`),
UNIQUE KEY `game_id_server_id` (`game_id`,`server_id`),
UNIQUE KEY `game_id_server_name` (`game_id`,`server_name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
因為有外鍵的存在,所以我不想改變字段類型,費勁啊。呵呵。雖然最後我還是選擇了更改字段類型,這是後話。因為我本篇日志想要說明的是varchar排序問題。所以不再說明我是如何更改字段類型的,大家有興趣可以搜索我以前的日志。(騙一下點擊)
現象描述:
下面,我從數據庫裡面以server_id排一下序,大家來看一下排序後的結果:
代碼如下 復制代碼
select server_id from cardserver where game_id = 1 order by server_id desc limit 10;
+-----------+
| server_id |
+-----------+
| 8 |
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 2 |
| 10 |
| 1 |
+-----------+
很明顯,我想要的結果應該是 10,8,7,6,5 這樣的。但是這個10排在了2的後面。按照字符串來排的。其實我是想把它當做數值來排。
手動轉換類型:
用下面的方法就可以了,使server_id+0之後再排序,問題解決了。
代碼如下 復制代碼
select server_id from cardserver where game_id = 1 order by server_id+0 desc limit 10;
+-----------+
| server_id |
+-----------+
| 10 |
| 8 |
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
+-----------+
使用MySQL函數CAST/CONVERT:
mysql為我們提供了兩個類型轉換函數:CAST和CONVERT,現成的東西我們怎能放過?
CAST() 和CONVERT() 函數可用來獲取一個類型的值,並產生另一個類型的值。
這個類型 可以是以下值其中的 一個:
BINARY[(N)]
CHAR[(N)]
DATE
DATETIME
DECIMAL
SIGNED [INTEGER]
TIME
UNSIGNED [INTEGER]
所以我們也可以用CAST解決問題:
代碼如下 復制代碼 select server_id from cardserver where game_id = 1 order by CAST(server_id as SIGNED) desc limit 10;
也可以使用CONVERT來搞定此問題:
select server_id from cardserver where game_id = 1 order by CONVERT(server_id,SIGNED) desc limit 10;
+-----------+
| server_id |
+-----------+
| 10 |
| 8 |
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
+-----------+
mysql按字母排序
數據表某字段client_name的字符編碼是utf8_general_ci;
代碼如下 復制代碼 SELECT * FROM `client_info_msg` ORDER BY CONVERT( client_name USING gbk ) COLLATE gbk_chinese_ci ASC;某字段name的字符編碼是latin1_swedish_ci;
Sql代碼
代碼如下 復制代碼 select * from `tbl` order by birary(name) asc一、1 CREATE TABLE NAME(name VARCHAR(10));
對這個表,缺省情況下,下面兩個查詢的結果是一樣的:
代碼如下 復制代碼SELECT * FROM TABLE NAME WHERE name='clip';
SELECT * FROM TABLE NAME WHERE name='Clip';
MySql默認查詢是不區分大小寫的,如果需要區分他,必須在建表的時候,Binary標示敏感的屬性.
代碼如下 復制代碼CREATE TABLE NAME(
name VARCHAR(10) BINARY
);
2 在SQL語句中實現 SELECT * FROM TABLE NAME WHERE BINARY name='Clip';
3 設置字符集:
utf8_general_ci –不區分大小寫
utf8_bin–區分大小寫
二、 MySQL在windows下是不區分大小寫的,將script文件導入MySQL後表名也會自動轉化為小寫,結果再 想要將數據庫導出放到linux服務器中使用時就出錯了。因為在linux下表名區分大小寫而找不到表,查了很多都是說在linux下更改MySQL的設 置使其也不區分大小寫,但是有沒有辦法反過來讓windows 下大小寫敏感呢。其實方法是一樣的,相應的更改windows中MySQL的設置就行了。
具體操作:
在MySQL的配置文件my.ini中增加一行:
代碼如下 復制代碼lower_case_table_names = 0
其中 0:區分大小寫,1:不區分大小寫
MySQL在Linux下數據庫名、表名、列名、別名大小寫規則是這樣的:
1、數據庫名與表名是嚴格區分大小寫的;
2、表的別名是嚴格區分大小寫的;
3、列名與列的別名在所有的情況下均是忽略大小寫的;
4、變量名也是嚴格區分大小寫的; MySQL在Windows下都不區分大小寫
所以MySql varchar排序我推薦使用CAST或CONVERT函數。