标签:
列属性: 主键, 自增长, 唯一键
?
关系: 一对一,一对多和多对多
范式: 三层范式
1NF: 字段设计必须符合原子性
2NF: 不存在部分依赖(没有复合主键)
3NF: 不存在传递依赖(实体单独建表)
逆规范化: 效率与磁盘空间的博弈
?
高级数据操作
新增操作: 主键冲突(更新和替换), 蠕虫复制
更新操作: 限制更新数量: limit
删除操作: 限制删除数量: limit, 清空表(truncate)
查询操作: select选项, 字段别名, 数据源(单表,多表和子查询[别名]),where子句(条件判断:从磁盘),groupby子句(分组统计,统计函数,分组排序, 多字段分组, 回溯统计), having子句(判断结果, 针对分组统计结果), orderby子句(排序, 多字段排序),limit子句(限制记录数,分页)
需求: 查询出所有的学生,而且要求显示学生所在的班级信息.
?
连接查询: 将多张表(可以大于2张)进行记录的连接(按照某个指定的条件进行数据拼接): 最终结果是: 记录数有可能变化, 字段数一定会增加(至少两张表的合并)
?
连接查询的意义: 在用户查看数据的时候,需要显示的数据来自多张表.
?
连接查询: join, 使用方式: 左表 join 右表
左表: 在join关键字左边的表
右表: 在join关键字右边的表
?
SQL中将连接查询分成四类: 内连接,外连接,自然连接和交叉连接
?
?
交叉连接: cross join, 从一张表中循环取出每一条记录, 每条记录都去另外一张表进行匹配: 匹配一定保留(没有条件匹配), 而连接本身字段就会增加(保留),最终形成的结果叫做: 笛卡尔积.
?
基本语法: 左表 cross join 右表; ===== from 左表,右表;
?
笛卡尔积没有意义: 应该尽量避免(交叉连接没用)
交叉连接存在的价值: 保证连接这种结构的完整性
?
内连接: [inner] join, 从左表中取出每一条记录,去右表中与所有的记录进行匹配: 匹配必须是某个条件在左表中与右表中相同最终才会保留结果,否则不保留.
?
基本语法
左表 [inner] join 右表 on 左表.字段 = 右表.字段; on表示连接条件: 条件字段就是代表相同的业务含义(如my_student.c_id和my_class.id)
?
字段别名以及表别名的使用: 在查询数据的时候,不同表有同名字段,这个时候需要加上表名才能区分, 而表名太长, 通常可以使用别名.
?
内连接可以没有连接条件: 没有on之后的内容,这个时候系统会保留所有结果(笛卡尔积)
?
内连接还可以使用where代替on关键字(where没有on效率高)
?
外连接: outer join, 以某张表为主,取出里面的所有记录, 然后每条与另外一张表进行连接: 不管能不能匹配上条件,最终都会保留: 能匹配正确保留; 不能匹配,其他表的字段都置空NULL.
?
外连接分为两种: 是以某张表为主: 有主表
Left join: 左外连接(左连接), 以左表为主表
Right join: 右外连接(右连接), 以右表为主表
?
基本语法: 左表 left/right join 右表 on 左表.字段 = 右表.字段;
?
左连接
?
右连接
?
虽然左连接和右连接有主表差异, 但是显示的结果: 左表的数据在左边,右表数据在右边.
?
左连接和右连接可以互转.
?
自然连接: natural join, 自然连接, 就是自动匹配连接条件: 系统以字段名字作为匹配模式(同名字段就作为条件, 多个同名字段都作为条件).
?
自然连接: 可以分为自然内连接和自然外连接.
?
自然内连接: 左表 natural join 右表;
?
自然外连接: 左表 natural left/right join 右表;
?
?
其实, 内连接和外连接都可以模拟自然连接: 使用同名字段,合并字段
左表 left/right/inner join 右表 using(字段名); -- 使用同名字段作为连接条件: 自动合并条件
?
多表连接: A表 inner join B表 on 条件 left join C表 on条件 ...
执行顺序: A表内连接B表,得到一个二维表, 左连接C表形成二维表...
?
?
事实上: PHP本身不能操作mysql, 但是PHP有扩展可以实现操作mysql: PHP借助扩展来实现操作mysql.
?
PHP操作mysql的扩展还挺多: mysql, mysqli和PDO扩展.
?
Mysql扩展: 纯面向过程, 里面都是函数,加载扩展后可以调用函数.(当前只能使用面向过程)
Mysqli扩展: 面向过程+面向对象,里面有函数也有类, 加载扩展后可以选择调用函数或者调用类操作.
PDO: 纯面向对象,只有类, 加载后只能调用类.
?
Mysql扩展在搭建服务器的时候就已经加载开启.不再进行扩展加载.
?
当PHP来对mysql进行操作之后: PHP的角色是mysql的一个客户端.
?
客户端操作服务端有必要的流程
数据库连接资源 Mysql_connect(服务器地址包含端口, 用户名, 用户密码);
?
默认的: mysql_connect会产生一个连接资源,即便是重新连接,也会返回原有的连接资源.
?
如果真的想产生多一个连接: 是新的,可以在mysql_connect函数的第四个参数控制: true
?
其实,根本不需要多个连接: 严重的资源浪费
?
Mixed Mysql_query(sql指令);
Boolean结果: SQL指令没有返回值, 布尔结果只能代表SQL语句没有语法错误, false就代表是SQL语句有语法错误: 主增删改
Resource结果: 结果集资源, SQL指令有结果返回(show, select),结果集永远为true: 主查询
?
?
Mysql_fetch_array: 默认获取混合数组,有一组关联,有一组索引.
?
当前函数可以实现: 只获取关联数组或者索引数组,通过第二个参数限制: MYSQL_BOTH是默认的,MYSQL_ASSOC是关联数组,MYSQL_NUM是索引数组.
关联数组获取: MYSQL_ASSOC
?
索引数组获取:MYSQL_NUM
?
Mysql_fetch_assoc: 直接获取关联数组
?
Mysql_fetch_row: 获取索引数组
?
不管是哪个fetch: 最终如果结果集指针移动到最后,返回都是false
Mysql_data_seek(结果集资源,位置从0开始);
Mysql_close(资源变量);
?
?
?
从计算机的角度出发: 增删改都属于写, 查属于读.
?
连接认证: 不一定连成功, 需要对结果进行判断: 可以直接使用三目运算(逻辑或)来进行处理, 但是无法获取错误信息. 如果要获取错误信息,那么需要使用mysql提供的获取错误的函数: mysql_errno()获取错误编号, mysql_error()获取错误信息.
?
在操作数据库之前要进行相关初始化: 设置字符集,选择数据库
?
发现: 其实所有的SQL语句都有可能出错: 将执行SQL语句,判断错误信息的代码进行封装: 封装成错误处理函数.
?
任何SQL语句的执行,都应该由my_error自定义函数来执行: 检查错误
?
写操作: 不符合人类的判断意识: 根据人的需求, 对进行进行分类操作: 增和删改
新增操作: 通常会获取当前新增记录的自增长id: mysql_insert_id(),直接获取上次新增操作的自增长ID, 如果没有自增长id获得0
?
删改操作: 通常都不能直接通过mysql_query的结果true来进行判断: true不代表执行成功,只代表SQL语句没有语法错误: 通过受影响的行数来判断是否成功: mysql_affected_rows()获取上次操作的受影响的行数(新增也有)
?
?
无外乎从数据库中查出所有数据, 最后在html里面显示.
?
在HTML显示数据
?
?
Mysql+PHP进行一个实际案例的综合应用.(HTML+CSS)
?
需求: 学生信息管理系统, 是一个后台管理系统, 显示学生的信息(管理:增删改), 分页功能. 需要用户登录之后才能查看数据信息.
?
功能: 登录功能, 分页显示数据功能
?
指导方针: 从用户角度出发, 顺着用户的操作步骤逐步进行.
?
?
所有的html文件都是放在project/templates/文件夹下: 所有的html文件,浏览器都不允许直接访问, 只允许访问PHP文件.
?
用户登录之后: 可以直接看到结果.
?
?
?
对应sql脚本:
-- 交叉连接 select * from my_student cross join my_class; -- my_student cross join my_class是数据源 ? -- 内连接 select * from my_student inner join my_class on my_student.c_id = my_class.id; select * from my_student inner join my_class on c_id = my_class.id; select * from my_student inner join my_class on c_id = id; -- 两张表都有id字段 ? -- 字段和表别名 select s.*,c.name as c_name,c.room from -- 字段别名 my_student as s inner join my_class as c -- 表别名 on s.c_id = c.id; ? ? -- where代替on select s.*,c.name as c_name,c.room from -- 字段别名 my_student as s inner join my_class as c -- 表别名 where s.c_id = c.id; ? -- 左连接 select s.*,c.name as c_name,c.room from my_student as s left join my_class as c -- 左表为主表: 最终记录数至少不少于左表已有的记录数 on s.c_id = c.id; ? -- 右连接 select s.*,c.name as c_name,c.room from my_student as s right join my_class as c -- 右表为主表: 最终记录数至少不少于右表已有的记录数 on s.c_id = c.id; ? ? select s.*,c.name as c_name,c.room from my_class as c right join my_student as s -- 左表为主表: 最终记录数至少不少于左表已有的记录数 on s.c_id = c.id; ? -- 自然内连接 select * from my_student natural join my_class; ? -- 自然左外连接 select * from my_student natural left join my_class; ? -- 外连接模拟自然外连接: using select * from my_student left join my_class using(id); |
?
?
?
标签:
原文地址:http://www.cnblogs.com/Prozhu/p/5763558.html