mysql中有很多的 保留字, 也叫关键字, 你在使用 数据库中的任何东西, 都最好是 避开这些关键字/保留字, 包括 数据库名, 表名, 字段名, 函数名, 存储过程名.
这些关键字包括:
mysql所谓的 ERROR1064错误, 就是语法错误, 语法错误只有两种情况: 要么是单词写错了. 是纯粹的 literal书写错误, 要么是第二种情况, 使用了mysql的保留关键字. 比如在定义函数的 时候, 最容易将 函数的 名称命名为 add. 而add恰好是mysql的关键字, 它是允许你 创建 add名称的 函数, 但是 当你 删除这个函数的 时候, 错误就来了. 所以还是那句话, 首先要有mysql关键字 保留字的概念, 然后 在定义的时候, 要 避开这些关键字.
也就是说, 在创建有关数据库的一切的时候, 都要 避开 关键字, 包括: 数据库名/表名/字段名/ 函数名/过程名等等. 但是如果你确实要使用,或者是以前的项目中已经使用了, 那么就要在这些名称两边加上 反引号, 那么就对这些 保留字进行了 转义, 就不再是 保留字了.
回到题目的问题, drop function add; 实际上 add是mysql 的保留字, 用于 给数据表 增加字段: alter table foo add age tinyint unsigned;
杂项
blob: Binary Large OBjects: 用来存储 二进制文件的内容, 比如: 图片和音乐等. 不是存储这些文件的名称, 而是 存储的这些文件的内容.包括 : tinyblob, blob,, mediumblob, largeblob
在存储开销和 检索效率上, char>varchar>text. 当然他们的存储长度依次增大 . 而效率依次减小. char和varchar必须指定长度. 而text可以不用指定长度, 即使指定长度值, 也没有多大意义.
在mysql中, 能够使用 数字类型的时候, 就尽量使用数字类型, 而不要使用 字符类型, 因为在检索和比较的时候, 数字类型的只比较一次, 而字符类型的要逐个逐个地比较 字符串中的 每个字符.
生成随机英文名字的存储过程:
drop procedure if exists sp_genRandEnName;
delimiter //
create definer='root'@'localhost' procedure sp_genRandEnName(in persons int unsigned)
comment 'this is random test data generator'
begin
declare i int unsigned default 0;
declare j int unsigned default 0;
declare ename char(20) default '';
declare nl tinyint default 0;
while i<persons do
set ename='';
set j=0;
set ename=concat(ename, ruc());
set nl=floor(3+16*rand());
repeat
set ename=concat(ename, rlc());
set j=j+1;
until j>nl end repeat;
insert into `user`(id, name) values('', ename);
set i=i+1;
end while;
end//
delimiter ;
删除表中的字段, 使用 drop 字段: alter table foo_table drop age;
case 语句的两种方式即两个版本, : 最最重要的是: case分成version1, 和 version2, 而且 分成 case operator 操作算子和 case statment 语句两种. 这两种方式的 语法和用途 是不同的, 可以查看mysql的help帮助.
一是操作算子operator:
-- 第一种语法, 是作为操作算子, 执行的方式是, 比较 expression 和后面的 expression1 或expression2 是否相等, 如果相等(注意 这里是比较的 相等. 是两个表达式, 没有比较运算符) , 则执行后面的 语句 序列(注意这里的语句是一个表达式, 要返回一个值, 因为这个值要作为select 的选择结果 ), 否则执行else 后面的 语句序列, 如果都不满足, 则返回null
case expression (表达式)
when expression1 then 表达式的值1
when expression2 then 表达式的值2
....
[else]
[比如begin ...end..语句列表]
end 注意 这里不能有case. 只能是end.
二是语句statement:
-- 第二种语法, 执行的方式是, 先判断when后面的 **条件表达式**,注意是条件表达式, 本身里面就包含了比较 , 则执行后面的 语句 序列, 否则执行else 后面的 语句序列, 如果都不满足, 则返回null
case
when condition_expression1 then statements
when condition_expression2 then statements
....
[else]
[比如begin ...end..语句列表]
end case 这里必须要有case.
### 总之, 第一种语法, 适合比较/ 判断 相等的情况; 而第二种语法, 适合 比较复杂 的 条件判断, 比如大于 小于等等条件的判断.
这是mysql本身的规定,和 语言特征, 只能对数据库中的表和字段进行comment, 不能对数据库本身进行注释
mysql中的enum枚举类型和set集合类型,是 复合类型的变量, 是mysql对标准sql的扩展. 他们 都是以字符串的形式出现的 , 只是 在数据库内部存储时, 是作为整数类型来处理的。 本身的列举值是字符串型。
enum 中的列举值默认的是 字符串类型, 但是在内部存储和处理的时候, 是作为 integer来的。
enum中的第一列举值的整数是从1 开始的, 不是从0 开始的。
你可以在赋值的时候, 插入记录的时候,如果你 给予 列举值之外的字符串, 而不会报错,只会给出警告。 这时候, 存储的时候 是以“空字符串”来表示的, 内部值是0. 因为你仍然可以用select gender+1 from user; 进行运算。
enum存储空间为 2个字节, 16位, 可以存储65535个值。每个值都对应着一个独立的 整数.
**如果说, enum相当于单选, 只能取列表值中的某一个值. 它通常用于表示互斥选项的数据列表. 那么set类型, 则是多选.因为有多个位, 对应位上的选项被选中, 则对应的位被置1, 正因为set是对应的多个位, 所以 他的多个值才能 同时出现, 并构成一个数值. **
同样的道理, 如果你赋予了一个不再选择数据范围内的值,比如你的值超过了 列表中所有位 相加的和, 则会插入一个 "空字符串" 或0 来代替 . 因此, 要查找非法 的set赋值, 只要查找空字符串或binary 二进制为0 的 记录.
程序编程语言中, 凡是 像set 一样,以一个数字来表示多个选择值的情况时, 通常是用位 来表示的, 以数字中的每一个位(对应的值分别为 1,2,4,8,16...)来表示一个 "选择值", 然后将所有的位 表示的值加起来得到所有选项对应的值
解析时, 对应的数值 是离散的, 不是连续的, 根据这些离散的数值, 就可以知道是哪些 "位"被选择, 这样就可以知道是哪些选项被选中.
set共8个字节, 共64位, 所以 一个位表示一个选项,所以 一个set可以有64个多选items.
站在mysql的角度上, 要多使用enum, 和set, 和cursor以及event trigger 等.因为可以增加mysql操作的效率, 尽量利用mysql数据库本身的处理能力. 但是站在php等编程的角度来说, 这些"所谓的" 高级应用 最好是 少用?? 因为他们的可移植性和可兼容性不是太好. 因为这些特性是mysql特征的(至少在语法上)其他数据库在语法和使用上不是完全一致的. 当然 如果你不考虑移植性, 你只在mysql上开发操作, 那就不用考虑这个问题, 该用就还是用, 只是好像有人说, "trigger, event"等最好是用在测试性的数据上, 不要用在你的重要数据上??
mysql中的 case有两种版本
一种是作为 operator操作因子, 通常用在select等语句中, 作为一个 表达式, 不能单独使用, 这时候, 他的syntax语法是, case .... end (注意这里不能用 end case, 只是一个end就可以了)
另一种是 做为一个 独立的 statement 语句, 此时, 可以单独使用 ,通常放在 函数或 存储过程中, 语法是case.... end case(这里就要使用 end case了 不能只是一个 end)
注意区别两种case的语法, 主要是结束语句的写法.
当然, 每一种 case中都有两种情况:
第一, case expr when expr2 then ...表达式判断相等, 和 直接判断条件表达式的两种写法, 还有在when...后有then, 而else后面没有then.
特别注意的是, 如果case作为一个operator, 由于他是要放在select后面的, 作为一个字段值, 所以then后面必须是一个表达式,一个值,不能是一个语句.否则就会报语法错误!
一个实例:
mysql> select
-> (case `gender`
-> when 'male' then '男'
-> when 'female' then '女'
-> else '错误'
-> end ) as '性别' -- 这里要注意, 如果不用 as '性别'的话, 会将整个case语句作为字段列名显示
-> from stud;
+------+
| 性别 |
+------+
| 男 |
| 女 |
| 男 |
| 错误 |
| 错误 |
+------+
5 rows in set (0.00 sec)
最重要的是 ,如何给set类型的 列赋值?
按照 位的 集合的思想, set的值,就是 列表中的 项, 所对应的位表示的数字的和 . set中的项目items的值从第一个开始, 依次是: 1, 2, 4,8 , 16... 如果对应的选项被选中, 则所在的位 置1, 否则, 某个选项没有被包含, 则对应的位 置0. 最后, 将这些位对应的数字 加起来的和 就是 给这个 set类型的 字段的 赋值. 注意 不能用set 类型的 取值样式 来 给set 变量字段赋值.
create table hob(`hobby` set('篮球', '羽毛球', '平棒球', '游泳') ) comment '集合例子' charset utf8;
MariaDB [test]> insert into hob values('篮球','羽毛球'); -- 这个表示 两个字符串类型的字段
ERROR 1136 (21S01): Column count doesn't match value count at row 1
MariaDB [test]> insert into hob values(set('篮球','羽毛球')); -- 用set样式的赋值也是错误的
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'set('篮球','羽毛球'))' at line 1
MariaDB [test]> insert into hob values(5); -- 用对应的位 选中时对应的值 相加: 篮球=1, 羽毛球=2, 平棒球=4, 游泳=8..
Query OK, 1 row affected (0.08 sec)
MariaDB [test]> select * from hob;
+------------------+
| hobby |
+------------------+
| 篮球,平棒球 |
一定要删除root密码为空的账户, 因为同是root 的用户名, 根据机器的不同, 可能有几个不同的账号.这时后, 要指明 "完整的"用户名, 即 -u后面的用户, 要用 user@machine_name的方式给出, 如果只是给出 -uroot 会默认的, 自动的认为是 root@localhost. 如果root@localhost有密码, 那么就会报错. 同是 不能使用 -h 127.0.0.1 的方式, 也不能使用 -D database的方式.
[foo@localhost ~]$ mysql -u 'root' -h '127.0.0.1' -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
[foo@localhost ~]$
[foo@localhost ~]$ mysql -u 'root@127.0.0.1' -p
Enter password: -- 这时候, 密码为空, 直接回车, 就能登入系统
Welcome to the MariaDB monitor. Commands end with ; or g.
Your MariaDB connection id is 3
Server version: 10.0.28-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
MariaDB [(none)]>