彻底理解mysql服务器的字符集转换问题
主要参考这三个文章:
https://www.xiariboke.com/article/4147.html
http://blog.sina.com.cn/s/blog_690c46500100k1nf.html
http://www.cnblogs.com/springmvc-hibernate/archive/2010/01/04/2484353.html
1. 字符集以数据库为对象来说, 可以分为数据库内部操作的字符集, (即: character_set_server, database, table,field)和数据库外部的字符集. 1. 其中 character_set_connection是在存储数据库 前的 经过字符集编码转换的 内容. 是 传人字符集. 而character_set_result则是从数据库内部将数据取出来, 发送到客户端时事先经过的编码内容. 是 输出时的字符集. 也就是说, connect的字符集 只是 管 传人的. 不管 输出的 , 而result才是 管输出的.
-
注意的是, character_set_client这个字符集, 它只是 向服务器 "声明" 说明的 字符集. 但并不表示 从客户端 (比如Php程序编辑器edit vim notepad等) 传入进来的sql 语句就一定是 (真的是) 这个client, 所以 client具有 欺骗性. 本身没有多大必然的用处.. 但也并不是一定用处都没有 : 当 把传入sql语句 存入 数据库之前, 要把sql语句 从 client指定的字符集 -> 转变为connect字符集. 就起这点作用!
所以, 最好不要去隐藏和欺骗服务器, 要尽量将 编辑器的字符集和 client的字符集一致 -
实际上, 所有的问题, 是 不只是要关注 数据库内部 的存储字符集, 还要关注 从 客户端到 服务器的 连接层 的 字符集: 就是 当 sql语句 连接进来后, 服务器收到 sql语句后, 并不是 马上 就进入 数据库进行存储, 而是要 先 放下来, 经过 connect 连接字符集的处理后, 才能 进入数据库. 这里, connect就相当于 数据库 进门时的 门卫和看守, 而character_set_result就相当于数据库 出库输出 内容的出门 时 的 门卫和看守, 都要 经果他们的 转换的!
每天自动对 mysql数据库的备份 shell脚本
-
备份命令: mysqldump -u root -p db_test > db_name.sql
还原: 有两种方法, 一是 进入mysql后, 执行 source命令;
二是, 还是在 shell下, 执行 mysql命令:mysql -u root -p db_name < db_name.sql
跟登录数据库的命令类似, 只是后面 要加上 ( 数据库名称< 脚本名称 )
推荐 用 第二种 mysql命令, 因为它可以直接在 shell下执行. -
一个常识: 在命令行操作 mysql的命令(相关命令)时, 一定要加上操作用户和密码选项. 这样mysql服务器才能 决定是否有权执行... 而且 指定密码的 方式是: -p 不要直接写密码值.
mysqladmin 提供了对mysql数据库 从外部的, 状态上的 一个管理, 主要包括这些命令:
mysqladmin [options] command comand [...]
最常见的选项是 -uroot -p 通常都要把这两个选项带上
- create/drop databsename, 只能创建数据库, 不能创建表, 而且不需要用 database这个关键字
- flush-... 刷新各种权限
- password 和 old-password 设置密码;
- 其他辅助命令, ping, processlist. shutdown, status, version, start/stop-slave 从服务器管理.
-
学会做人生的减法了.
-
现在就是只 管php和mysq语言了, 太多的东西, 已经不能兼顾了.
-
要把mysql当作是一个独立的开发语言, 熟悉并能熟练应用 它里面的函数和各种结构的用法.
-
mysql中的字符串函数包括:
ascii/char : 将数字和字符进行转换的函数. 比如:ascii('abc') 总是转换第一字符, 配合substr可以 查看任何一个字符, char(89)转换数字到字符
cast(变量/字段 as to_type): mysql的类型转换函数, 强制转换;
concat 字符串连接函数: 可以将最终返回字符串 str_ret跟中间 结果的字符串 相连接, 节省一个中间变 量; 可以将数字和数字字符串相连接, 或将数字和字母字符串相连接;
+: 在mysql中,加号总是用来表示 数字相加, 如果是字符串用加号连接, 总是 尽量 /企图 将"数字字符串" 转换成数字, 所以 如果是字母字符串跟数字相加, 则总是将 字母字符串忽略即为0..mysql> select 2a + 3; ERROR 1054 (42S22): Unknown column '2a' in 'field list' mysql> select '2a' + 3; +----------+ | '2a' + 3 | +----------+ | 5 | +----------+ 1 row in set, 1 warning (0.00 sec) mysql>
字符串截取函数: left(str, length), right(str, length), substring(str, start, length),
substring_index(str, delimiter, length).
其中, mid, subst函数 是 substring函数的别名alias.
需要注意的是, 所有的mysql的字符串截取函数, 首字符start都是从1开始的. 而不是从0开始的.
uuid()函数, 生成36位的随机字符串: 8-4-4-4-12(个数) 的 随机字符串. 分成5个部分: 8, 4,4,4 , 12.
但是uuid()不适合用来做主键!
replace(str, from, to): replace("abc-amn-axy", 'a", '#'): 结果是: #bc-#mn-#xy.
instr(haystack, needle): 判断needle在hay中的初始出现的位置,从1开始, 如果没有找到则返回0,hay为 null也返回0.
rand()是生成在0和1之间的 随机数. 可以给rand指定一个参数, 作为种子, 那么 rand(seed)会产生固定的相同的随机数, 改变N种子, 也就能够改变随机数.
rand() 函数也不需要 进行播种..
要生成 x~ y之间的随机数, 可以使用: x+(y-x)*rand(); 这个随机数是小数, 还要用 round或floor, ceil来生成整数. 其中 , floor可以得到下限值, 比如x, ceil可以得到 上限值, 比如 y.
2. 只有 “字符”类型的字段,比如char, varchar, text等才需要指定字符集编码和 collate。其他比如 int, boolean等类型类型则不需要指定 字符集.
-
使用$where = " where 1 "; 然后后面的所有条件语句的拼接都可以 and 的统一形式进行书写, 而不 用去判断是否是第一个条件字符串...
-
是否可以用 charset 来代替 character set?
在help create table中, 提示的是 : [default] character set [=] charset_name. 当然你可以用 character set utf8 来指定, 但是 你也可以 [肯定是可以的] 用 charset 来指定. 而且即使你用 character set来指定的字符集, 你用show create table foo;来查看, 显示的结果也是 用的 charset...mysql> create table bar(id int not null) character set utf8; Query OK, 0 rows affected (0.05 sec) mysql> show create table bar; +-------+-------------------------------------------------------- ------------+ | Table | Create Table | +-------+-------------------------------------------------------- ------------+ | bar | CREATE TABLE `bar` ( `id` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | ### 这里的字符集指定都是用的 charset这种简写方式, 和 character set 这种全写方式, 完全是一样的! +-------+-------------------------------------------------------- ------------+ 1 row in set (0.00 sec)
-
select 10 where 1; 为什么报错?
where子句, 只能使用 在 对 "数据表"的 操作中! 也就是里面要有表, 要有字段, 否则就会出错. -
对于where子句来说, 通常是不区分大小写的, 只有在使用 like 条件运算符的时候, 才区分大小写! 如果要区分大小,可以使用 binary关键字, 就是以字节位单位来比较的.
-
length是按字节来计算的. 而char_length 是按字符个数来计算长度的.
-
在mysql中的循环语句, 没有/不支持 for 循环语句! 只有while do end while; repeat util end repeat; lp1: loop ... leave lp1...end loop语句!
对于mysql而言, 根本就不需要适用 图形化的 客户端界面, 因为那种方式 效率太低, 不能理解/记忆很多的mysql操作语句, 不能深入理解了解mysql的内在, 所以 直接使用 mysql的命令行控制台客户端, 这是每个linux程序员最基本的素质.
关于select中的rand() 函数的使用??
- 也就是说, select实际上有两个作用, 有两种使用场景: 一是: 纯粹的输出, print, output, 并不牵涉到 "表的 查询" ! 另一种是: 对表的 操作中, 作为 对表的 查询 动作;
- **select语句中, 如果牵涉到 表的 查询, 最好是 不要使 用 rand() 函数, 因为使用rand随机函数时, 会进行多次计算和查询. 通常 应该将确定性的 函数如 max, avg , count等放在 select 对 表的 查询语句中, 然后, 将 rand()函数 用在 跟 查询结果的 四则运算中. **
- 要注意的是, select about_function(rand())语句中, select只是 起到 "输出 "的作用, 并没有 查询的 意思和操作!
比如:select * from student where id > round(rand()*(select max(id) from student))
如果要抽出 多个随机性的记录行结果?
应该使用的方法是: 第一 ,要 能够正确的 适用 rand()函数, 第二, 要在一次查询操作中, 只输出一个 记录行, 然后使用mysql中的循环结构多次输出...
即:
while i< rec_num do
select * from student where id > round(rand()*(select max(id) from student)) limit 1; # id > round(...)的记录有很多个, 我们每次只选择一个limit 1.
end while
但是 这个有可能会取到跟上一次 一样的记录, (同一条记录) 因此, 要判断一下, 当前取出的这条记录的某个关键字(key, 或 primary key) 跟上一条记录的primary key是否是一样的, 如果不是一样的 , 则接收, 同时 计数器i 加1, ... 如果是一样的 , 则不接收, 放弃后面的操作, 同时 i也不要 增加.
set @pre_id=0;
set @cur_id=0;
while i< rec_num do
select id into @sel_id , other_filed into @other_field from user where id > round(rand()*(select max(id) from use)) limit 1;
if @pre_id <> @sel_id then
set i=i+1;
-- 返回 @sel_id, @other_field
end if;
if @pre_id = @cur_id then
-- 此时 循环变量i 不要加1
end if;
end while
在mysql中, 可以直接使用 变量, 而不必 事先定义该变量. 但是一个变量, 如果事先没有声明 初始化赋值, 那么 它的值就是 NULL, NULL跟任何东西运算,都将得到NULL.
MariaDB [test]> select @pre_name;
+-----------+
| @pre_name |
+-----------+
| NULL |
+-----------+
1 row in set (0.00 sec)
MariaDB [test]>
在 select语句中, 给 变量赋值 有两种方式, 即 select ...into, select a:=b
select name into @name from t where...
第二种方法是: select @name2:=name from t where ...
在这两种方法中, 都不需要 事先 声明/定义/初始化 变量 @name @name2等.
注意的是, select中 不能 直接使用 a=b 的方式 来 赋值.
关于mysql中的特殊 常量?
有三个特殊的常量: TRUE, FALSE, NULL
这三个特殊常量, 是不分大小写的! 比如: true, True, 都是和TRUE一样的, 同样null和 Null 更 NULL也是一样的! 在写法上没有区别!
mysql的特殊类型 boolean和 tinyint?
在mysql中, 是没有boolean 类型的. 而true 和 false 是当做 tinyint(1)来处理的, 注意 这里的1, 表示 的是, 只显示一位数! 并不是说它的取值范围.
mysql中的游标cursor 的使用? http://www.cnblogs.com/Luouy/p/7301360.html
mysql中的 循环有三种, while ,和 loop 和 repeat中的 "break 和 continue?"
- loop和 repeat中 就相当于 c/c++语言中的 do ....while(condition...)
- mysql中, 使用 break和continue的对应 关键字 是: iterate 和 leave
- 但是要配合 标号/标识表示: 比如: loop_name: lp: