数据库SQL语句的使用

1、创建SQL语句 DDL语句

MySQL命令行参数:

Usage: mysql [OPTIONS] [database]   //命令方式
 -?, --help          //显示帮助信息并退出
 -I, --help          //显示帮助信息并退出
 --auto-rehash       //自动补全功能,就像linux里面,按Tab键出提示差不多,下面有例子
 -A, --no-auto-rehash  //默认状态是没有自动补全功能的。-A就是不要自动补全功能
 -B, --batch         //ysql不使用历史文件,禁用交互
 (Enables --silent)
 --character-sets-dir=name   //字体集的安装目录                    
 --default-character-set=name    //设置数据库的默认字符集
 -C, --compress      //在客户端和服务器端传递信息时使用压缩
 -#, --debug[=#]     //bug调用功能
 -D, --database=name //使用哪个数据库
 --delimiter=name    //mysql默认命令结束符是分号,下面有例子
 -e, --execute=name  //执行mysql的sql语句
 -E, --vertical      //垂直打印查询输出
 -f, --force         //如果有错误跳过去,继续执行下面的
 -G, --named-commands 
 -g, --no-named-commands
 -i, --ignore-spaces //忽视函数名后面的空格.
 --local-infile      //启动/禁用 LOAD DATA LOCAL INFILE.
 -b, --no-beep       //sql错误时,禁止嘟的一声
 -h, --host=name     //设置连接的服务器名或者Ip
 -H, --html          //以html的方式输出
 -X, --xml           //以xml的方式输出
 --line-numbers      //显示错误的行号
 -L, --skip-line-numbers  //忽略错误的行号
 -n, --unbuffered    //每执行一次sql后,刷新缓存
 --column-names      //查寻时显示列信息,默认是加上的
 -N, --skip-column-names  //不显示列信息
 -O, --set-variable=name  //设置变量用法是--set-variable=var_name=var_value
 --sigint-ignore     //忽视SIGINT符号(登录退出时Control-C的结果)
 -o, --one-database  //忽视除了为命令行中命名的默认数据库的语句。可以帮跳过日志中的其它数据库的更新。
 --pager[=name]      //使用分页器来显示查询输出,这个要在linux可以用more,less等。
 --no-pager          //不使用分页器来显示查询输出。
 -p, --password[=name] //输入密码
 -P, --port=#        //设置端口
 --prompt=name       //设置mysql提示符
 --protocol=name     //使用什么协议
 -q, --quick         //不缓存查询的结果,顺序打印每一行。如果输出被挂起,服务器会慢下来,mysql不使用历史文件。
 -r, --raw           //写列的值而不转义转换。通常结合--batch选项使用。
 --reconnect         //如果与服务器之间的连接断开,自动尝试重新连接。禁止重新连接,使用--disable-reconnect。
 -s, --silent        //一行一行输出,中间有tab分隔
 -S, --socket=name   //连接服务器的sockey文件
 --ssl               //激活ssl连接,不激活--skip-ssl
 --ssl-ca=name       //CA证书
 --ssl-capath=name   //CA路径
 --ssl-cert=name     //X509 证书
 --ssl-cipher=name   //SSL cipher to use (implies --ssl).
 --ssl-key=name      //X509 密钥名
 --ssl-verify-server-cert //连接时审核服务器的证书
 -t, --table         //以表格的形势输出
 --tee=name          //将输出拷贝添加到给定的文件中,禁时用--disable-tee
 --no-tee            //根--disable-tee功能一样
 -u, --user=name     //用户名
 -U, --safe-updates  //Only allow UPDATE and DELETE that uses keys.
 -U, --i-am-a-dummy  //Synonym for option --safe-updates, -U.
 -v, --verbose       //输出mysql执行的语句
 -V, --version       //版本信息
 -w, --wait          //服务器down后,等待到重起的时间
 --connect_timeout=# //连接前要等待的时间
 --max_allowed_packet=# //服务器接收/发送包的最大长度
 --net_buffer_length=# //TCP / IP和套接字通信缓冲区大小。
 --select_limit=#    //使用--safe-updates时SELECT语句的自动限制
 --max_join_size=#   //使用--safe-updates时联接中的行的自动限制
 --secure-auth       //拒绝用(pre-4.1.1)的方式连接到数据库
 --server-arg=name   //Send embedded server this as a parameter.
 --show-warnings     //显示警告

1.1、数据库操作

// SQL命令用大写作为普遍的使用规范。
// 创建数据库
CREATE DATABASE 数据库名;
// 判断数据库是否存在并设置字符集编码
CREATE DATABASE 数据库名 [DEFAULT CHARACTER SET '字符编码']; //不能使用 “-” 
// 进入一个数据库
USE 数据库名;
// 查看当前数据库
SELECT database();
// 查看数据库
SHOW DATABASES;
SHOW DATABASES LIKE '匹配模式'; // _单个匹配 %多个匹配;可以同时使用
// 查看数据库的创建信息和字符集编码
SHOW CREATE DATABASE 数据库名;
// 更改数据库信息 (一般不用)
ALTER DATABASE 数据库名 CHARSET 字符集;
// 删除数据库
DROP DATABASE 数据库名;
DROP DATABASE [IF EXISTS] 数据库名; // IF EXISTS 判断是否存在 存在删除

1.2、数据表操作

// 创建数据表必须同时创建表中的字段
CREATE TABLE 表名(
    id TINYINT PRIMARY KEY auto_increment,// PRIMARY KEY 主键 auto_increment自动增长
    name VARCHAR(25),
    gender boolean,
    age INT  COMMENT '年龄',
    department VARCHAR(20),
    salary DOUBLE(7,2)
)ENGINE=INNODB DEFAULT CHARSET=utf8; // ENGINE=INNODB 指定数据库使用的执行引擎,INNODB才支持事务。

CREATE TABLE 数据库名.表名(
    数据的字段信息
)DEFAULT CHARSET 'utf8';

/*约束条件:
NOT NULL : 用于控制字段的内容一定不能为空(NULL)。
UNIQUE : 控件字段内容不能重复,一个表允许有多个 Unique 约束。
PRIMARY KEY: 用于控件字段内容不能重复,但它在一个表只允许出现一个。
FOREIGN KEY  REFERENCES : 1、约束用于预防破坏表之间连接的动作,FOREIGN KEY 约束。
             2. 也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
CHECK: 用于控制字段的值范围。
DEFAULT: 用于设置默认值。
*/

// 查看数据库中的所有表
SHOW TABLES;

// 查看表结构
DESC 表名; // 全称 DESCRIBE 表名;

// 查询mysql表字段信息的sql语句 
SHOW DATABASES                                 //列出 MySQL Server 数据库。
SHOW TABLES [FROM db_name]                     //列出数据库数据表。
SHOW CREATE TABLES tbl_name                    //数据表结构。
SHOW TABLE STATUS                              //列出数据表及表状态信息。
SHOW COLUMNS FROM tbl_name [FROM db_name]      //列出资料表字段
SHOW FIELDS FROM tbl_name [FROM db_name]       // 查看表结构
SHOW FULL COLUMNS FROM tbl_name [FROM db_name]    //列出字段及详情
SHOW FULL FIELDS FROM tbl_name [FROM db_name]     //列出字段完整属性
SHOW INDEX FROM tbl_name [FROM db_name]           //列出表索引。
SHOW STATUS                                       //列出 DB Server 状态。
SHOW VARIABLES                                    //列出 MySQL 系统环境变量。
SHOW PROCESSLIST                                  //列出执行命令。
SHOW GRANTS FOR user                              //列出某用户权限

// 修改表名
RENAME TABLE 修改的表名 to 新表名

// 添加字段
ALTER TABLE 表名 ADD 字段名 限制条件,ADD 字段名 限制条件;

// 修改一列类型
ALTER TABLE 表名 MODIFY 字段名 类型 [完整性约束条件] [firse | after 字段名];

一: 修改表信息
修改表名 
ALTER TABLE test_a RENAME TO sys_app;

修改表注释   
ALTER TABLE sys_application COMMENT'系统信息表';
 

二:修改字段信息
修改字段类型和注释
ALTER TABLE sys_application  MODIFY COLUMN app_name varchar(20) COMMENT '应用的名称';

修改字段类型
ALTER TABLE sys_application MODIFY COLUMN app_name TEXT;

设置字段允许为空
ALTER TABLE sys_application MODIFY COLUMN description VARCHAR(255) NULL COMMENT '应用描述';

增加一个字段,设好数据类型,且不为空,添加注释
ALTER TABLE sys_application ADD  `url` VARCHAR(255) NOT NULL COMMENT '应用访问地址';  

增加主键 
ALTER TABLE t_app ADD aid INT(5) NOT NULL , ADD PRIMARY KEY (aid);  

增加自增主键
ALTER TABLE t_app ADD aid INT(5) NOT NULL AUTO_INCREMENT , ADD PRIMARY KEY (aid); 

修改为自增
ALTER TABLE t_app MODIFY COLUMN aid INT(5) AUTO_INREMENT;

修改字段名字(要重新指定该字段的类型)
ALTER TABLE t_app CHANGE NAME app_name VARCHAR(20) NOT NULL;

删除字段
ALTER TABLE t_app DROP aid; 

在某个字段后增加字段
ALTER TABLE t_app ADD COLUMN gateway_id INT NOT NULL DEFAULT 0 AFTER `aid`; #(在 aid 字段后面添加 gateway_id 字段)
  
调整字段顺序 
ALTER TABLE t_app CHANGE gateway_id gateway_id INT NOT NULL AFTER aid ; #(注意gateway_id出现了2次,把gateway_id放在aid之前)

修改字段默认值语法:

ALTER TABLE 表名 ALTER COLUMN 字段名 DROP DEFAULT; (若本身存在默认值,则先删除)
ALTER TABLE 表名 ALTER COLUMN 字段名 SET DEFAULE 默认值;(若本身不存在则可以直接设定)

// 删除一个字段
ALTER TABLE 表名 DROP 字段;

// 删除主键
ALTER TABLE 表名 DROP PRIMARY KEY;
ALTER TABLE table_name DROP PRIMARY KEY;

// 创建多个主键,多个外键关联 
CONSTRAINT 外键名称 FOREIGN KEY 创建外键名称 REFERENCES 表名(字段名) ON 约束条件

CREATE TABLE `score` (
 `sid`  int NOT NULL AUTO_INCREMENT ,
 `student_id`  int NOT NULL ,
 `corse_id`  int NOT NULL ,
 `number`  int NOT NULL ,
 PRIMARY KEY (`sid`, `student_id`, `corse_id`),
 CONSTRAINT `student_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`sid`) ON DELETE NO ACTION,
 CONSTRAINT `corse_id` FOREIGN KEY (`corse_id`) REFERENCES `course` (`cid`) ON DELETE NO ACTION
);
-- PS:字段名包裹用的是符号“ ` ”,而不是英文的“ '' ”,其他地方用“ '' 或者 "" ”包裹内容。

1.2.1、数字型

类型

大小

范围(有符号)

范围(无符号)

用途

TINYINT

1 字节

(-128,127)

(0,255)

小整数值

SMALLINT

2 字节

(-32 768,32 767)

(0,65 535)

大整数值

MEDIUMINT

3 字节

(-8 388 608,8 388 607)

(0,16 777 215)

大整数值

INT或INTEGER

4 字节

(-2 147 483 648,2 147 483 647)

(0,4 294 967 295)

大整数值

BIGINT

8 字节

(-9 233 372 036 854 775 808,9 223 372 036 854 775 807)

(0,18 446 744 073 709 551 615)

极大整数值

FLOAT

4 字节

(-3.402 823 466 E+38,1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38)

0,(1.175 494 351 E-38,3.402 823 466 E+38)

单精度
浮点数值

DOUBLE

8 字节

(1.797 693 134 862 315 7 E+308,2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)

0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)

双精度
浮点数值

DECIMAL

对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2

依赖于M和D的值

依赖于M和D的值

小数值/1。2.

1.2.2、字符串类型

类型

范围

说明

 

Char(N)

[ binary]

N=1~255 个字元
binary :分辨大小写

固定长度

std_name cahr(32) not null

VarChar(N)[binary]

N=1~255 个字元
binary :分辨大小写

可变长度

std_address varchar(256)

TinyBlob

最大长度255个字元(2^8-1)

Blob (Binary large objects)储存二进位资料,且有分大小写

Text 文本字符

memo text not null

TinyText

最大长度255个字元(2^8-1)

Blob

最大长度65535个字元(2^16-1)

Text

最大长度65535个字元(2^16-1)

MediumBlob

最大长度 16777215 个字元(2^24-1)

MediumText

最大长度 16777215 个字元(2^24-1

LongBlob

最大长度4294967295个字元 (2^32-1)

LongText

最大长度4294967295个字元 (2^32-1)

Enum

集合最大数目为65535

列举(Enumeration),Enum单选、Set复选

sex enum(1,0)
habby set(‘玩电玩’,'睡觉’,'看电影’,'听音乐’)

Set

集合最大数目为64

1.2.3、时间日期类型

日期时间类型 占用空间 日期格式 最小值 最大值 零值表示
 DATETIME  8 bytes  YYYY-MM-DD HH:MM:SS  1000-01-01 00:00:00 9999-12-31 23:59:59  0000-00-00 00:00:00
 TIMESTAMP  4 bytes  YYYY-MM-DD HH:MM:SS  19700101080001 2038 年的某个时刻 00000000000000
 DATE  4 bytes  YYYY-MM-DD 1000-01-01  9999-12-31  0000-00-00
 TIME  3 bytes  HH:MM:SS  -838:59:59 838:59:59  00:00:00
 YEAR  1 bytes  YYYY 1901  2155  0000

1.3、内容操作  

1.3.1、查询语句的执行循序
from -> where -> select -> group by -> having -> order by

1.3.2、查询语句的基本总结

// 从.sql文件引入SQL语句
SOURCE <.SQL文件路径>;

// MySQL可以进行 +,-,*,/ 运算
// 写入内容
INSERT INTO 表名 (字段,字段2,....) VALUES (字段的值,字段值2,....)

INSERT INTO 表名 SET 字段名=字段的值,字段名2=字段的值2;

// 查看表中的内容 \G:将查到的结构纵向显示,后不用加结束符如“;”。
SELECT *(字段) FROM 表名\G;
SELECT 字段,字段2 FROM 表名;

// distinct 过滤重复的内容
SELECT [DISTINCT] * FROM 表名; 
SELECT 字段 as 字段别名 FROM 表名;

// 查询学过“001”并且也学过编号“002”课程的同学的学号、姓名; 
// 子查询 exists(SELECT *(字段) FROM 表名;)
SELECT Student.S#,Student.Sname FROM Student,SC 
    WHERE Student.S#=SC.S# AND SC.C#='001' AND 
    EXISTS( SELECT * FROM SC AS SC_2 WHERE SC_2.S#=SC.S# AND SC_2.C#='002'); 

// WHERE 语句筛选
SELECT * FROM 表名 WHERE 条件;
/*  比较运算符(=、<>、!=、>、>=、!>、<、<=、!<)
    between 80 and 100; 值在80到100之间 between...and 和 not between and
    in(80,90,100); 值是80或90或100 用来指定列表搜索的条件;
    like 'yuan%'; 
    // pattern可以是 % 或 _ ;如果是 % 则表示任意多字符,比如唐%,唐僧,唐国强都符合;
    // 如果是 _ 则表示一个字符,唐_ 只有 唐僧 符合,可以加多根 _ ;如唐__ 唐国强符合;
    多个条件直接使用逻辑运算符 and:与 or:或 not:非 is:判断
*/

// 排序 Order by 条件 desc 降序(从大到小) asc 升序(从小到大) 
SELECT 字段 FROM 表名 WHERE 条件 LIKE 'yuan%' ORDER BY 排序条件 DESC;  

// 分组 group by  按分组条件分组后,每一组只显示第一条记录,其他隐藏在组里面。
SELECT * FROM 表名 GROUP BY 按此字段分组;

/* 聚合函数 
    SUM(字段名)   求指定字段列的和
    COUNT(字段名) 返回指定字段列的行数
    AVG(字段名)   返回指定字段列的平均值
    MIN(字段名)   返回指定字段列的最小值
    MAX(字段名)   返回指定字段列的最大值
*/
SELECT name,sum(字段名) FROM 表名 GROUP BY 字段;


// 对分组后进行过滤 having 
SELECT name,sum(字段名) FROM 表名 GROUP BY 字段 HAVING sum(字段名)>150;

// limit 获取显示的条数
SELECT * FROM 表名 WHERE 过滤条件 LIMIT 1,5; // 获取到 >=1 <5 的内容

// MySQL 正则
SELECT * FROM 表名 WHERE 过滤条件 REGEXP '正则表达式';

// 修改内容
UPDATE 表名 SET 字段名=字段的值,字段名2=字段的值2  WHERE 条件 ;
UPDATE 表名 SET 字段名=字段的值,字段名2=字段的值2  WHERE id=10 ;
UPDATE 表名 SET 字段名=replace(字段名,'旧内容','新内容') WHERE ID < 200;


// 删除内容

DELETE FROM 表名; // 清空表内容 (逐条删除表中的数据)

DELETE FROM 表名 WHERE 条件; // 删除条件符合的一条内容

    WHERE 字段=字段值 AND 字段1=字段值1;

TRUNCATE TABLE 表名;// 删除整张表后再重新创建字段。

// 判断语句的使用
// 查询不为空的数据 is [not] 值
SELECT * FROM 表名 WHERE 字段 IS NOT NULL GROUP BY 按此字段分组;

// top 语句
SELECT TOP 4 * FROM 表名; // 显示前四条信息

1.4、运算符

1.算术运算符
+     加   SET var1=2+2;       4
-     减   SET var2=3-2;       1
*     乘   SET var3=3*2;       6
/     除   SET var4=10/3;      3.3333
DIV   整除 SET var5=10 DIV 3;  3
%     取模 SET var6=10%3 ;     1

2.比较运算符
>                   大于                         1>2 False
<                   小于                         2<1 False
<=                  小于等于                      2<=2 True
>=                  大于等于                      3>=2 True
BETWEEN             在两值之间                    5 BETWEEN 1 AND 10 True
NOT BETWEEN         不在两值之间                  5 NOT BETWEEN 1 AND 10 False
IN                  在集合中                      5 IN (1,2,3,4) False
NOT IN              不在集合中                    5 NOT IN (1,2,3,4) True
=                   等于                          2=3 False
<>, !=              不等于                        2<>3 False
<=>                 严格比较两个NULL值是否相等      NULL<=>NULL True
LIKE                简单模式匹配                   "Guy Harrison" LIKE "Guy%" True
REGEXP              正则式匹配                     "Guy Harrison" REGEXP "[Gg]reg" False
IS NULL             为空                           0 IS NULL False
IS NOT NULL         不为空                         0 IS NOT NULL True

3.位运算符
|   或
&   与
<< 左移位
>> 右移位
~   非(单目运算,按位取反)

4.注释:mysql存储过程可使用两种风格的注释
双横杠:-- 用于单行注释

c风格:/* 注释内容 */ 用于多行注释


5.分支结构
if
case

6.循环结构
for循环
while循环
loop循环
repeat until循环

注:
区块定义,常用
begin
......
end;
也可以给区块起别名,如:
lable:begin
...........
end lable;
可以用leave lable;跳出区块,执行区块以后的代码。

2、外键

// 外键的使用
// 绑定外键
CREATE TABLE 表名(
    // 作为外键一定要与关联的主键数据类型保持一致
    FOREIGN KEY  (需要绑定外键的字段名)  REFERENCES 表名(id(表字段))
)

// 删除关联的内容,需要解除关联关系,或者同时删除相关联的内容。

// 添加外键关联
ALTER TABLE 表名 ADD CONSTRAINT 自定义外键名 FOREIGN KEY (需要绑定外键的字段名) REFERENCES 被绑定表名(id);

// 删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名;

// 多表查询
SELECT * FROM users u INNER JOIN user_info AS ui WHERE u.info_id = ui.id;

3、on语句

// 外键级联 设置了之后删除主表数据同时也删除了子表记录。
CREATE TABLE 表名(
    字段,
    FOREIGN KEY (需要绑定外键的字段名) REFERENCES 被绑定表名(id) ON DELETE CASCADE
) 

// set NULL  会把子表的记录变成NULL
CREATE TABLE 表名(
    字段,
    FOREIGN KEY (需要绑定外键的字段名) REFERENCES 被绑定表名(id) ON DELETE SET NULL
)                          

4、外联查询,多表操作

// 多表查询之联接查询
// 内联接查询 INNER JOIN
// 外联接查询 LEFT JOIN  RIGHT JOIN
// 全联接 FULL JOIN (不支持)

// 内联接查询
    SELECT * FROM 表名1,表名2 WHERE 表名1.id=表名2.表名1_id;

    // 查询与where子句相匹配的信息
    SELECT * FROM table1,table2 WHERE table1.id=table2.table1_id; 

    // 查询与where子句相匹配的字段信息
    SELECT table1.id,table1.name,table2.name WHERE table1.id=table2.table1_id;
    
    // 对表名2中匹配表名1中的内容进行查询
    // 只显示符合 on 条件信息
    SELECT * FROM 表名2 INNER JOIN 表名1 ON 表名1.id=表名2.表名1_id; 
    

// 外联接查询 
    // 显示 on 后符合条件的信息,而且不符合条件的已NULL显示
    SELECT * FROM 表名1 LEFT JOIN 表名2 ON 条件;// 已左表为主查询符合条件的信息,并显示
    SELECT * FROM 表名1 RIGHT JOIN 表名2 ON 条件;// 已右表为主查询符合条件的信息

4.2、内联接查询

内联接要应用两个逻辑查询处理步骤:它首先像交叉联接一样,对两个输入表进行笛卡尔积运算;然后根据用户指定的谓词对结果行进行过滤。

使用内联接须在两个表之间指定INNER JOIN关键字,当然,INNER关键字是可选的,因为内联接是默认的联接方式,所以可单独指定JOIN关键字。然后利用ON关键字对结果行进行过滤,该谓词也称为联接条件。

下面是一个内联接查询的例子,它对HR数据库中的Employees表和Sales数据库中的Order表执行内联接运算,然后根据谓词条件employees.empid = orders.empid对职员和订单记录进行匹配。

-- INNER JOIN内联接查询
SELECT employees.empid,employees.firstname,employees.lastname,orders.orderid 
FROM HR.Employees employees
JOIN Sales.Orders orders ON employees.empid = orders.empid

4.2、外联接查询

外联接除了有内联接的两个逻辑处理步骤(即笛卡尔积和ON过滤)之外,还多加一个外联接特有的第三步:添加外部行。

在外联接中,需要将一个表标记为保留表,在两个表之间用LEFT OUTER JOIN连接(OUTER是可选的),LEFT关键字左边表的行是保留的。外联接的第三个逻辑查询处理步骤就是要识别保留表中按照ON条件在另一个表中找不到与之匹配的那些行,然后将这些行添加到联接的前两个步骤生成的结果表中。对于来自联接的非保留表的那些列,追加的外部行中的这些列则用NULL作为占位符。

4.2.1、外联接三表查询示例

使用 LEFT JOIN ... ON ... 语句实现
SELECT
    a.body,b.title,c.typename 
FROM
    dede_addonarticle a 
LEFT JOIN
    dede_archives b 
ON  
    a.typeid=b.typeid
LEFT JOIN
    dede_arctype c 
ON 
    a.typeid=c.id ;

查询结果:

数据库SQL语句的使用_第1张图片

4.2.2、外联接的注意事项

对于外联接查询的总结,需要注意以下几点:

  1. 从外联接保留表的角度看,可以认为外联接结果的数据行包括两种:内部行和外部行。内部行是按照ON子句的条件能在联接的另一边找到匹配的那些行;而外部行则是指找不到匹配的那些行。内联接只返回内部行,而外联接同时返回内部行和外部行。
  2. 使用外联接的时候,经常会为到底是在查询的ON子句中,还是在WHERE子句中指定联接条件而困惑。现在的结论是,当需要表达一个非最终的条件时(即这个条件只决定哪些行可以匹配非保留表),就在ON子句中指定联接条件;当在生成外部行后,要应用过滤器,并且希望过滤条件是最终的,就应该在WHERE子句中指定条件。
  3. 当查找NULL值时,应该使用IS NULL运算符,而不是直接使用等号,因为等号会把任何值与NULL进行比较时,总是会返因UNKNOWN---即使对两个NULL值进行比较也是这样。
  4. 选择联接的非保留表中的哪个列作为过滤器也很重要。应该选择只在外部行才取值为NULL,而在其他行取值不为NULL的某个列。为此,有三种情形可以考虑安全地使用,主键列,联接列,以及定义为NOT NULL的列。具体可以参考下面的查询代码。
  5. 跨数据库查询示例:Sales数据库中的Customers表与HR数据库中的Orders表进行外联接查询。
SELECT customers.custid,customers.companyname,orders.orderid 
FROM Sales.Customers AS customers
LEFT JOIN HR.Orders AS orders ON customers.custid = orders.custid
WHERE orders.orderid IS NULL -- 使用主键列
-- WHERE orders.custid IS NULL --使用联接列
-- WHERE orders.orderdate IS NULL -- 使用NOT NULL列
-- PS:Sales.Customers 表示 数据库名.表名

5、索引(对表的操作)

数据库索引详细介绍

// 索引查询
CREATE TABLE 表名 (
        字段1 数据类型 [完整性约束条件...],
        字段2 数据类型 [完整性约束条件...],
        // 索引名
        [UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY 
        [索引名] (字段名[(长度)] [ASC | DESC]) 
);
// INDEX | KEY  普通索引

CREATE TABLE 表名 (
    id INT,
    name VARCHAR(30),
    resume VARCHAR(50),
    INDEX index_name (name)
)
// index_name 索引的名称

// 创建唯一索引
CREATE TABLE 表名 (
    id INT,
    name VARCHAR(30),
    UNIQUE INDEX index_name (name)
);
// unique index 表示唯一索引

// 创建全文索引
CREATE TABLE 表名 (
    id INT,
    name VARCHAR(30),
    FULLTEXT INDEX index_name (name)
);

// 创建多列索引
CREATE TABLE 表名 (
    id INT,
    name VARCHAR(30),
    age INT,
    INDEX index_name_age (name,age)
);



// 在已存在的字段中添加索引
CREATE [UNIQUT|FULLTEXT|SPATIAL] INDEX 索引名 ON 表名(字段名[(长度)] [ASC|DESC]);
ALTER TABLE 表名 ADD  [UNIQUT|FULLTEXT|SPATIAL] INDEX 索引名 ON 表名(字段名[(长度)] [ASC|DESC]);

// 删除索引
DROP INDEX 索引名 ON 表名;
ALTER TABLE 表名 DROP INDEX 索引名;

DROP INDEX index_name ON table_name ;
ALTER TABLE table_name DROP INDEX index_name ;

6、函数基本用法

MySQL函数分为自身的内置函数和自定义函数两种形式,查看 MySQL内置函数的使用 

自定义函数(user-defined function UDF)就是用一个象ABS() 或 CONCAT()这样的固有(内建)函数一样作用的新函数去扩展MySQL,所以UDF是对MySQL功能的一个扩展,UDF可以没有参数,但UDF必须有且只有一个返回值。

创建UDF:

CREATE [AGGREGATE] FUNCTION function_name(parameter_name type,[parameter_name type,...])

RETURNS {STRING|INTEGER|REAL}

runtime_body

/*
CREATE FUNCTION 函数名称(参数列表)

RETURNS 返回值类型

函数体
*/

删除UDF:

DROP FUNCTION function_name

调用自定义函数语法:

SELECT function_name(parameter_value,...)

更对自定义函数的使用方法点击查看:MySQL自定义函数具体使用方法

7、数据库事务

// 开启事务
start transaction;
Rollback 回滚事务,即撤销指定的sql语句(只能回退insert delete update语句)
Commit 提交事务,提交未存储的事务
savepoint 保留点,事务处理中设置的临时占位符,可以对它发布回退(与整个事务回退不同)

// 保留点的使用

insert delete update 语句后面紧跟 savepoint 语句就为该语句设置了保留点

savepoint 保留点名; //设置保留点

// 回滚到指定的保留点

rollback to 保留点名; // 回滚到指定的保留点位置

8、数据库关于锁的规则

-- 数据库锁,保证数据执行正常

bejin; -- 开启事务
select * from 表名 for update; -- 表锁, for update 加锁
select * from 表名 where id=1 for update; -- 行锁
commit; -- 释放事务

8.1、MySQL引擎

引擎名称

优点

缺陷

应用场景

MyISAM

独立于操作系统,这说明可以轻松地将其从Windows服务器移植到Linux服务器,支持表级锁

不支持事务/行级锁/外键约束

适合管理邮件或Web服务器日志数据

InnoDB

健壮的事务型存储引擎;支持事务/表级锁/行级锁/外键约束自动灾难恢复/AUTO_INCREMENT

 

需要事务支持,并且有较高的并发读取频率

MEMORY

为得到最快的响应时间,采用的逻辑存储介质是系统内存

当mysqld守护进程崩溃时,所有的Memory数据都会丢失;不能使用BLOB和TEXT这样的长度可变的数据类型

临时表

MERGE

是MyISAM类型的一种变种。合并表是将几个相同的MyISAM表合并为一个虚表

 

常应用于日志和数据仓库

ARCHIVE

归档的意思,支持索引,拥有很好的压缩机制

仅支持插入和查询功能

经常被用来当做仓库使用

8.2、查看引擎的启用情况

1、查看数据库的存储引擎

show engines; //查看mysql所有支持的引擎

//进入数据库,执行这个命令
show variables like '%storage_engine%'; # 查看当前数据库使用的引擎

2、查看当前数据库的字符编码

show variables like '%character_set%';

3、查看数据库的版本号

//进入数据库之后,执行status即可
mysql>status

4、关于varchar

MySQL5.0.3之前varchar(n)这里的n表示字节数;

MySQL5.0.3之后varchar(n)这里的n表示字符数,比如varchar(200),不管是英文还是中文都可以存放200个。

9、触发器

触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行。触发器触发条件,在增删改操作的前后进行操作。

--基本语法
CREATE TRIGGER trigger_name trigger_time trigger_event ON table_name FOR EACH ROW
trigger_stmt

其中:

trigger_name:标识触发器名称,用户自行指定;
trigger_time:标识触发时机,取值为 BEFORE 或 AFTER;
trigger_event:标识触发事件,取值为 INSERT、UPDATE 或 DELETE;
table_name:标识建立触发器的表名,即在哪张表上建立触发器;
trigger_stmt:触发器程序体,可以是一句SQL语句,或者用 BEGIN 和 END 包含的多条语句。

由此可见,可以建立6种触发器,即:BEFORE INSERT、BEFORE UPDATE、BEFORE DELETE、AFTER INSERT、AFTER UPDATE、AFTER DELETE。

另外有一个限制是不能同时在一个表上建立2个相同类型的触发器,因此在一个表上最多建立6个触发器。

9.1、trigger_event 详解

MySQL 除了对 INSERT、UPDATE、DELETE 基本操作进行定义外,还定义了 LOAD DATA 和 REPLACE 语句,这两种语句也能引起上述6中类型的触发器的触发。

LOAD DATA 语句用于将一个文件装入到一个数据表中,相当与一系列的 INSERT 操作。

REPLACE 语句一般来说和 INSERT 语句很像,只是在表中有 primary key 或 unique 索引时,如果插入的数据和原来primary key 或 unique 索引一致时,会先删除原来的数据,然后增加一条新数据,也就是说,一条 REPLACE 语句有时候等价于一条 INSERT 语句,有时也等价于一条 DELETE 语句加上一条 INSERT 语句。

INSERT 型触发器:插入某一行时激活触发器,可能通过 INSERT、LOAD DATA、REPLACE 语句触发;
UPDATE 型触发器:更改某一行时激活触发器,可能通过 UPDATE 语句触发;
DELETE 型触发器:删除某一行时激活触发器,可能通过 DELETE、REPLACE 语句触发。

DELIMITER $

 -- 为takes表创建名为credit_get的update触发器,在更新之后(after)执行
 create trigger credit_get after update on takes for each row
 begin
    -- if条件判断成立执行then后的语句
    if (NEW.grade <> 'F' and NEW.grade is not null) and (OLD.grade = 'F' or OLD.grade is null)) 
    then
    update student set tot_cred = tot_cred + (select credits from course where course.course_id = NEW.course_id) where student.ID = NEW.ID;
    end if;
 end $

DELIMITER ;

注意事项:

after触发器-->是在记录操纵之后触发,是先完成数据的增删改,再触发,触发的语句晚于监视的增删改操作,无法影响前面的增删改动作;

before触发器-->是在记录操纵之前触发,是先完成触发,再增删改,触发的语句先于监视的增删改,我们就有机会判断,修改即将发生的操作;如:我们在触发之前需要判断new值和old值的大小或关系,如果满足要求就触发,不通过就修改再触发;如:表之间定义的有外键,在删除主键时,必须要先删除外键表,这时就有先后之分,这里before相当于设置了断点,我们可以处理删除外键。

对于INSERT语句, 只有NEW是合法的;

对于DELETE语句,只有OLD才合法;

对于UPDATE语句,NEW、OLD可以同时使用。

9.2、BEGIN … END 详解

在MySQL中,BEGIN … END 语句的语法为:

BEGIN
[statement_list]
END

其中,statement_list 代表一个或多个语句的列表,列表内的每条语句都必须用分号(;)来结尾。而在MySQL中,分号是语句结束的标识符,遇到分号表示该段语句已经结束,MySQL可以开始执行了。因此,解释器遇到statement_list 中的分号后就开始执行,然后会报出错误,因为没有找到和 BEGIN 匹配的 END。

这时就会用到 DELIMITER 命令(DELIMITER 是定界符,分隔符的意思),它是一条命令,不需要语句结束标识,语法为:

DELIMITER new_delemiter 
new_delemiter 可以设为1个或多个长度的符号,默认的是分号(;),我们可以把它修改为其他符号,如$:
DELIMITER $ 在这之后的语句,以分号结束,解释器不会有什么反应,只有遇到了$,才认为是语句结束。注意,使用完之后,我们还应该记得把它给修改回来。

例子:

假设系统中有两个表:
班级表 class(班级号 classID, 班内学生数 stuCount)
学生表 student(学号 stuID, 所属班级号 classID)
要创建触发器来使班级表中的班内学生数随着学生的添加自动更新,代码如下:

DELIMITER $ --定义语句终止符为“$”
 --为student表创建名为tri_stuInsert的insert触发器,在创建之前(before)执行
 create trigger tri_stuInsert before insert on student for each row
 begin --开始
   declare c int; -- 定义 c 为 int 类型
   set c = (select stuCount from class where classID=new.classID); -- set 变量名=设置值;
   update class set stuCount = c + 1 where classID = new.classID;
 end$ --end表示结束,“$” 表示语句结束。
DELIMITER ;

9.3、变量详解

MySQL 中使用 DECLARE 来定义一局部变量,该变量只能在 BEGIN … END 复合语句中使用,并且应该定义在复合语句的开头,即其它语句之前,语法如下:

DECLARE var_name[,...] type [DEFAULT value]

其中:

var_name 为变量名称,同 SQL 语句一样,变量名不区分大小写;type 为 MySQL 支持的任何数据类型;可以同时定义多个同类型的变量,用逗号隔开;变量初始值为 NULL,如果需要,可以使用 DEFAULT 子句提供默认值,值可以被指定为一个表达式。

对变量赋值采用 SET 语句,语法为:

SET var_name = expr [,var_name = expr] ...

9.4、NEW 与 OLD 详解

上述示例中使用了NEW关键字,和 MS SQL Server 中的 INSERTED 和 DELETED 类似,MySQL 中定义了 NEW 和 OLD,用来表示触发器的所在表中,触发了触发器的那一行数据。

具体地:
在 INSERT 型触发器中,NEW 用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
在 UPDATE 型触发器中,OLD 用来表示将要或已经被修改的原数据,NEW 用来表示将要或已经修改为的新数据;
在 DELETE 型触发器中,OLD 用来表示将要或已经被删除的原数据;

使用方法: NEW.columnName (columnName 为相应数据表某一列名),另外,OLD 是只读的,而 NEW 则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用(如每插入一个学生前,都在其学号前加“2013”)。

9.4、查看触发器

和查看数据库(show databases;)查看表格(show tables;)一样,查看触发器的语法如下:

SHOW TRIGGERS [FROM schema_name];

其中,schema_name 即 Schema 的名称,在 MySQL 中 Schema 和 Database 是一样的,也就是说,可以指定数据库名,这样就不必先“USE database_name;”了。

9.5、删除触发器

和删除数据库、删除表格一样,删除触发器的语法如下:

DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name

9.6、触发器的执行顺序

我们建立的数据库一般都是 InnoDB 数据库,其上建立的表是事务性表,也就是事务安全的。这时,若SQL语句或触发器执行失败,MySQL 会回滚事务,有:

a、MySQL的触发器是按照BEFORE触发器、行操作、AFTER触发器的顺序执行的,其中任何一步发生错误都不会继续执行剩下的操作。

b、如果 BEFORE 触发器执行失败,SQL 无法正确执行。

c、SQL 执行失败时,AFTER 型触发器不会触发。

d、AFTER 类型的触发器执行失败,SQL 会回滚。

9.7、限制

触发器会有以下两种限制:

1、触发程序不能调用将数据返回客户端的存储程序,也不能使用采用CALL语句的动态SQL语句,但是允许存储程序通过参数将数据返回触发程序,也就是存储过程或者函数通过OUT或者INOUT类型的参数将数据返回触发器是可以的,但是不能调用直接返回数据的过程。

2、不能再触发器中使用以显示或隐式方式开始或结束事务的语句,如START TRANS-ACTION,COMMIT或ROLLBACK。

10、视图(view)

// 视图:视图被称为虚拟表,存放在数据库中,并且视图只能进行查询。
 // 创建视图
  CREATE VIEW 视图名 AS sql语句;
 // 修改视图
  CREATE OR REPLACE VIEW 视图名 AS select语句;
 // 使用
  SELECT * FROM 视图名;
 // 删除视图
 DROP VIEW 视图名;

10.1、视图的基本概念

视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据库中的。通过视图,可以展现基表的部分数据;视图数据来自定义视图的查询中使用的表,使用视图动态生成。使用视图的大部分情况是为了保障数据安全性,提高查询效率。

基表:用来创建视图的表叫做基表base table。

视图优点:

  1)简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。

  2)安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。

  3)数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

10.2、创建视图

CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
    VIEW view_name [(column_list)]
    AS select_statement
   [WITH [CASCADED | LOCAL] CHECK OPTION]

1)OR REPLACE:表示替换已有视图

2)ALGORITHM:表示视图选择算法,默认算法是UNDEFINED(未定义的):MySQL自动选择要使用的算法 ;merge合并;temptable临时表

3)select_statement:表示select语句

4)[WITH [CASCADED | LOCAL] CHECK OPTION]:表示视图在更新时保证在视图的权限范围之内

  cascade是默认值,表示更新视图的时候,要满足视图和表的相关条件

  local表示更新视图的时候,要满足该视图定义的一个条件即可

TIPS:推荐使用WHIT [CASCADED|LOCAL] CHECK OPTION选项,可以保证数据的安全性 

基本格式:

  create view <视图名称>[(column_list)]

       as select语句

       with check option;

1、在单表上创建视图

mysql> create view v_F_players(编号,名字,性别,电话)
    -> as
    -> select PLAYERNO,NAME,SEX,PHONENO from PLAYERS
    -> where SEX='F'
    -> with check option;
Query OK, 0 rows affected (0.00 sec)
mysql> desc v_F_players;

+--------+----------+------+-----+---------+-------+
| Field  | Type     | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| 编号    | int(11)  | NO   |     | NULL    |       |
| 名字    | char(15) | NO   |     | NULL    |       |
| 性别    | char(1)  | NO   |     | NULL    |       |
| 电话    | char(13) | YES  |     | NULL    |       |
+--------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> select * from  v_F_players;
+--------+-----------+--------+------------+
| 编号    | 名字      | 性别    | 电话        |
+--------+-----------+--------+------------+
|      8 | Newcastle | F      | 070-458458 |
|     27 | Collins   | F      | 079-234857 |
|     28 | Collins   | F      | 010-659599 |
|    104 | Moorman   | F      | 079-987571 |
|    112 | Bailey    | F      | 010-548745 |
+--------+-----------+--------+------------+
5 rows in set (0.02 sec)

2、在多表上创建视图

mysql> create view v_match
    -> as 
    -> select a.PLAYERNO,a.NAME,MATCHNO,WON,LOST,c.TEAMNO,c.DIVISION
    -> from 
    -> PLAYERS a,MATCHES b,TEAMS c
    -> where a.PLAYERNO=b.PLAYERNO and b.TEAMNO=c.TEAMNO;


Query OK, 0 rows affected (0.03 sec)
mysql> select * from v_match;

+----------+-----------+---------+-----+------+--------+----------+
| PLAYERNO | NAME      | MATCHNO | WON | LOST | TEAMNO | DIVISION |
+----------+-----------+---------+-----+------+--------+----------+
|        6 | Parmenter |       1 |   3 |    1 |      1 | first    |
|       44 | Baker     |       4 |   3 |    2 |      1 | first    |
|       83 | Hope      |       5 |   0 |    3 |      1 | first    |
|      112 | Bailey    |      12 |   1 |    3 |      2 | second   |
|        8 | Newcastle |      13 |   0 |    3 |      2 | second   |
+----------+-----------+---------+-----+------+--------+----------+
5 rows in set (0.04 sec)
视图将我们不需要的数据过滤掉,将相关的列名用我们自定义的列名替换。视图作为一个访问接口,不管基表的表结构和表名有多复杂。  
如果创建视图时不明确指定视图的列名,那么列名就和定义视图的select子句中的列名完全相同;
如果显式的指定视图的列名就按照指定的列名。
注意:显示指定视图列名,要求视图名后面的列的数量必须匹配select子句中的列的数量。

10.3、查看视图

1、使用show create view语句查看视图信息

mysql> show create view v_F_players\G;
*************************** 1. row ***************************
                View: v_F_players
         Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_F_players` AS select `PLAYERS`.`PLAYERNO` AS `编号`,`PLAYERS`.`NAME` AS `名字`,`PLAYERS`.`SEX` AS `性别`,`PLAYERS`.`PHONENO` AS `电话` from `PLAYERS` where (`PLAYERS`.`SEX` = 'F') WITH CASCADED CHECK OPTION
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.00 sec)

2、视图一旦创建完毕,就可以像一个普通表那样使用,视图主要用来查询

mysql> select * from view_name;

3、有关视图的信息记录在information_schema数据库中的views表中

mysql> select * from information_schema.views 
    -> where TABLE_NAME='v_F_players'\G;
*************************** 1. row ***************************
       TABLE_CATALOG: def
        TABLE_SCHEMA: TENNIS
          TABLE_NAME: v_F_players
     VIEW_DEFINITION: select `TENNIS`.`PLAYERS`.`PLAYERNO` AS `编号`,`TENNIS`.`PLAYERS`.`NAME` AS `名字`,`TENNIS`.`PLAYERS`.`SEX` AS `性别`,`TENNIS`.`PLAYERS`.`PHONENO` AS `电话` from `TENNIS`.`PLAYERS` where (`TENNIS`.`PLAYERS`.`SEX` = 'F')
        CHECK_OPTION: CASCADED
        IS_UPDATABLE: YES
             DEFINER: root@localhost
       SECURITY_TYPE: DEFINER
CHARACTER_SET_CLIENT: utf8
COLLATION_CONNECTION: utf8_general_ci
1 row in set (0.00 sec)   

10.4、视图的更改

1、CREATE OR REPLACE VIEW语句修改视图

基本格式:

create or replace view view_name as select语句;

在视图存在的情况下可对视图进行修改,视图不在的情况下可创建视图

2、ALTER语句修改视图

ALTER
    [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
    [DEFINER = { user | CURRENT_USER }]
    [SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
    [WITH [CASCADED | LOCAL] CHECK OPTION]

注意:修改视图是指修改数据库中已存在的表的定义,当基表的某些字段发生改变时,可以通过修改视图来保持视图和基本表之间一致

3、DML操作更新视图

  因为视图本身没有数据,因此对视图进行的dml操作最终都体现在基表中

mysql> create view v_student as select * from student;

mysql> select * from v_student;


+--------+--------+------+
| 学号    | name   | sex  |
+--------+--------+------+
|      1 | 张三    | M    |
|      2 | 李四    | F    |
|      5 | 王五    | NULL |
+--------+--------+------+
mysql> update v_student set name='钱六' where 学号='1';

mysql> select * from student;

+--------+--------+------+
| 学号    | name   | sex  |
+--------+--------+------+
|      1 | 钱六    | M    |
|      2 | 李四    | F    |
|      5 | 王五    | NULL |
+--------+--------+------+

当然,视图的DML操作,不是所有的视图都可以做DML操作。

有下列内容之一,视图不能做DML操作:

  ①select子句中包含distinct

  ②select子句中包含组函数

  ③select语句中包含group by子句

  ④select语句中包含order by子句

  ⑤select语句中包含union 、union all等集合运算符

  ⑥where子句中包含相关子查询

  ⑦from子句中包含多个表

  ⑧如果视图中有计算列,则不能更新

  ⑨如果基表中有某个具有非空约束的列未出现在视图定义中,则不能做insert操作

4、drop删除视图

  删除视图是指删除数据库中已存在的视图,删除视图时,只能删除视图的定义,不会删除数据,也就是说不动基表:

DROP VIEW [IF EXISTS]   
view_name [, view_name] ...


mysql> drop view v_student;

如果视图不存在,则抛出异常;使用IF EXISTS选项使得删除不存在的视图时不抛出异常。

10.5、使用WITH CHECK OPTION约束 

对于可以执行DML操作的视图,定义时可以带上WITH CHECK OPTION约束

作用:

  对视图所做的DML操作的结果,不能违反视图的WHERE条件的限制。

示例:创建视图,包含1960年之前出生的所有球员(老兵)

mysql> create view v_veterans
    -> as
    -> select * from PLAYERS
    -> where birth_date < '1960-01-01'
    -> with check option;


Query OK, 0 rows affected (0.01 sec)
mysql> select * from v_veterans;
+----------+---------+----------+------------+-----+--------+----------------+---------+----------+-----------+------------+----------+
| PLAYERNO | NAME    | INITIALS | BIRTH_DATE | SEX | JOINED | STREET         | HOUSENO | POSTCODE | TOWN      | PHONENO    | LEAGUENO |
+----------+---------+----------+------------+-----+--------+----------------+---------+----------+-----------+------------+----------+
|        2 | Everett | R        | 1948-09-01 | M   |   1975 | Stoney Road    | 43      | 3575NH   | Stratford | 070-237893 | 2411     |
|       39 | Bishop  | D        | 1956-10-29 | M   |   1980 | Eaton Square   | 78      | 9629CD   | Stratford | 070-393435 | NULL     |
|       83 | Hope    | PK       | 1956-11-11 | M   |   1982 | Magdalene Road | 16A     | 1812UP   | Stratford | 070-353548 | 1608     |
+----------+---------+----------+------------+-----+--------+----------------+---------+----------+-----------+------------+----------+
3 rows in set (0.02 sec)

此时,使用update对视图进行修改:

mysql> update v_veterans
    -> set BIRTH_DATE='1970-09-01'
    -> where PLAYERNO=39;

ERROR 1369 (HY000): CHECK OPTION failed 'TENNIS.v_veterans'

因为违反了视图中的WHERE birth_date < '1960-01-01'子句,所以抛出异常;

利用with check option约束限制,保证更新视图是在该视图的权限范围之内。

嵌套视图:定义在另一个视图的上面的视图

mysql> create view v_ear_veterans
    -> as
    -> select * from v_veterans
   -> where JOINED < 1980;

使用WITH CHECK OPTION约束时,(不指定选项则默认是CASCADED)

可以使用CASCADED或者 LOCAL选项指定检查的程度:

  ①WITH CASCADED CHECK OPTION:检查所有的视图

    例如:嵌套视图及其底层的视图

  ②WITH LOCAL CHECK OPTION:只检查将要更新的视图本身

    对嵌套视图不检查其底层的视图 

10.6、定义视图时的其他选项

CREATE [OR REPLACE]   
  [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]  
  [DEFINER = { user | CURRENT_USER }]  
  [SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]  
AS select_statement  
  [WITH [CASCADED | LOCAL] CHECK OPTION]

1、ALGORITHM选项:选择在处理定义视图的select语句中使用的方法

  ①UNDEFINED:MySQL将自动选择所要使用的算法

  ②MERGE:将视图的语句与视图定义合并起来,使得视图定义的某一部分取代语句的对应部分

  ③TEMPTABLE:将视图的结果存入临时表,然后使用临时表执行语句

缺省ALGORITHM选项等同于ALGORITHM = UNDEFINED

2、DEFINER选项:指出谁是视图的创建者或定义者

  ①definer= '用户名'@'登录主机'

  ②如果不指定该选项,则创建视图的用户就是定义者,指定关键字CURRENT_USER(当前用户)和不指定该选项效果相同

3、SQL SECURITY选项:要查询一个视图,首先必须要具有对视图的select权限。

  但是,如果同一个用户对于视图所访问的表没有select权限,那会怎么样?

SQL SECURITY选项决定执行的结果:

  ①SQL SECURITY DEFINER:定义(创建)视图的用户必须对视图所访问的表具有select权限,也就是说将来其他用户访问表的时候以定义者的身份,此时其他用户并没有访问权限。

  ②SQL SECURITY INVOKER:访问视图的用户必须对视图所访问的表具有select权限。

缺省SQL SECURITY选项等同于SQL SECURITY DEFINER 

视图权限总结:

  使用root用户定义一个视图(推荐使用第一种):u1、u2

    1)u1作为定义者定义一个视图,u1对基表有select权限,u2对视图有访问权限:u2是以定义者的身份访问可以查询到基表的内容;

    2)u1作为定义者定义一个视图,u1对基表没有select权限,u2对视图有访问权限,u2对基表有select权限:u2访问视图的时候是以调用者的身份,此时调用者是u2,可以查询到基表的内容。

10.7、视图查询语句的处理

示例:所有有罚款的球员的信息

创建视图:

mysql> create view cost_raisers
    -> as
    -> select * from PLAYERS
    -> where playerno in (select playerno from PENALTIES);

查询视图:

mysql> select playerno from cost_raisers
    -> where town='Stratford';
+----------+
| PLAYERNO |
+----------+
|        6 |
+----------+ 

1、替代方法:

  先把select语句中的视图名使用定义视图的select语句来替代;

  再处理所得到的select语句。

mysql> select playerno from
   -> (
    ->   select * from PLAYERS
    ->   where playerno in -> (select playerno from PENALTIES)
    -> ) as viewformula
    -> where town='Stratford';
+----------+
| PLAYERNO |
+----------+
|        6 |
+----------+

2、具体化方法:

  先处理定义视图的select语句,这会生成一个中间的结果集;

  然后,再在中间结果上执行select查询。

       mysql> select <列名> from <中间结果>; 

11、数据库存储过程

存储过程如同一门程序设计语言,同样包含了数据类型、流程控制、输入和输出和它自己的函数库。

11.1、创建存储过程

-- 修改SQL语句的结束符
delimiter $$ --将 “;” 修改为了 “$$”
例:SHOW TABLES$$

-- 存储过程使用

CREATE PROCEDURE 存储过程名() 
    BEGIN -- 存储过程代码开始
        declare i int default 1;-- 定义变量 i 默认值为 1
        while (1<50000) do
            INSERT INTO 数据库名.表名 VALUES (i,'yuan');
        set i=i+1; -- 设置变量
        end while; --结束while循环
    END$$ -- 存储过程代码结束

11.2、调用存储过程

基本语法:call sp_name()
注意:存储过程名称后面必须加括号,哪怕该存储过程没有参数传递

11.3、删除存储过程

1.基本语法:
drop procedure sp_name;

2.注意事项:不能在一个存储过程中删除另一个存储过程,只能调用另一个存储过程

11.4、其他常用命令

1.show procedure status;
显示数据库中所有存储的存储过程基本信息,包括所属数据库,存储过程名称,创建时间等。

2.show create procedure sp_name;
显示某一个MySQL存储过程的详细信息。

11.5、存储过程参数

IN 输入参数
表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值。

OUT 输出参数
该值可在存储过程内部被改变,并可返回。

INOUT 输入输出参数
调用时指定,并且可被改变和返回。

例子:

IN参数例子:

CREATE PROCEDURE sp_demo_in_parameter(IN p_in INT)
BEGIN
  SELECT p_in; --查询输入参数
  SET p_in=2; --修改
  SELECT p_in;--查看修改后的值
END;

执行结果:

SET @p_in=1

CALL sp_demo_in_parameter(@p_in)

SELECT @p_in;

以上可以看出,p_in虽然在存储过程中被修改,但并不影响@p_id的值

OUT参数例子:

CREATE PROCEDURE sp_demo_out_parameter(OUT p_out INT)
BEGIN
  SELECT p_out;/*查看输出参数*/
  SET p_out=2;/*修改参数值*/
  SELECT p_out;/*看看有否变化*/
END;

执行结果:

SET @p_out=1

CALL sp_demo_out_parameter(@p_out)

SELECT @p_out;

INOUT参数例子:

CREATE PROCEDURE sp_demo_inout_parameter(INOUT p_inout INT)
BEGIN
  SELECT p_inout;
  SET p_inout=2;
  SELECT p_inout;
END;

执行结果:

SET @p_inout=1

CALL sp_demo_inout_parameter(@p_inout) 

SELECT @p_inout;
 

你可能感兴趣的:(MySQL)