线程理论

进程
	进程其实是资源单位 表示一块内存空间
线程 
	线程才是执行单位 表示真正的代码指令

# 为啥要有线程呢
  开设线程的消耗远远小于进程
  开进程的步骤:
    1.申请内存空间
    2.拷贝代码
  开线程的步骤:
    一个进程内可以有多个线程 无需申请内存空间、拷贝代码
    一个进程内的多个线程是共享的

创建线程的两种方式

1.函数创建线程
from threading import Thread
import time

def task(name):
    print(f'{name} is running')
    time.sleep(3)
    print(f'{name} is over')
    
t = Thread(target=task, args=('owen',))
t.start()
print('主线程')

'''
创建线程无需考虑反复执行问题
'''
2.用对象创建线程
from threading import Thread
import time

class MyThread(Thread):
    def __init__(self,username):
        super().__init__()
        self.username = username
    def run(self):
        print(f'{self.username} is running')
        time.sleep(3)
        print(f'{self.username} is over')
        
t = MyThread('owen')
t.start()
print('主线程')

线程的诸多特性

1.join方法
2.同进程内多个线程数据共享
3.current_thread()
4.active_count()

GIL全局解释器锁

# 官方文档
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly 
because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
"""
1.在CPython解释器中存在全局解释器锁简称GIL
	python解释器有很多类型
		CPython JPython PyPython (常用的是CPython解释器)
		
2.GIL本质也是一把互斥锁 用来阻止同一个进程内多个线程同时执行(重要)

3.GIL的存在是因为CPython解释器中内存管理不是线程安全的(垃圾回收机制)
	垃圾回收机制
		引用计数、标记清除、分代回收
    
GIL只存在于CPython解释器中,不是python的特征
GIL是一把互斥锁用于阻止同一个进程下的多个线程同时执行
原因是因为CPython解释器中的垃圾回收机制不是线程安全的

反向验证GIL的存在 如果不存在会产生垃圾回收机制与正常线程之间数据错乱
GIL是加在CPython解释器上面的互斥锁
同一个进程下的多个线程要想执行必须先抢GIL锁 所以同一个进程下多个线程肯定不能同时运行 即无法利用多核优势

强调:同一个进程下的多个线程不能同时执行即不能利用多核优势
 python是垃圾 速度太慢 有多核都不能用
反怼:虽然用一个进程下的多个线程不能利用多核优势 但是还可以开设多进程!!!

再次强调:python的多线程就是垃圾!!!
反怼:要结合实际情况 
如果多个任务都是IO密集型的 那么多线程更有优势(消耗的资源更少)
		多道技术:切换+保存状态
如果多个任务都是计算密集型 那么多线程确实没有优势 但是可以用多进程
	CPU越多越好
以后用python就可以多进程下面开设多线程从而达到效率最大化
"""
1.所有的解释型语言都无法做到同一个进程下多个线程利用多核优势
2.GIL在实际编程中其实不用考虑

验证多线程作用

需要分情况
	情况1
    	单个CPU
        多个CPU
    情况2
    	IO密集型(代码有IO操作)
        计算密集型(代码没有IO)

# 1.单个CPU
	IO密集型
    	多进程
        申请额外的空间 消耗更多的资源
        多线程
        消耗的资源相对较少 通过多道技术
        ps:多线程有优势!!!
 	
    计算密集型
    	多进程
        申请额外空间 消耗更多的资源(总耗时+申请空间+拷贝代码+切换)
        多线程
        消耗资源相对较少 通过多道技术(总耗时+切换)
        ps:多线程有优势!!!
            
# 2.多个CPU
	IO密集型
    	多进程
        	总耗时(单个进程的耗时+IO+申请空间+拷贝代码)
        多线程
        	总耗时(单个进程的耗时+IO)
        ps:多线程有优势!!!
            
    计算密集型
    	多进程
        	总耗时(单个进程的耗时)
        多线程
        	总耗时(多个进程的综合)
        ps:多进程完胜!!!

计算密集型

 # 多进程   
from multiprocessing import Process
import time

def work():
    res = 1
    for i in range(1, 10000):
        res *= i

if __name__ == '__main__':
    # print(os.cpu_count())  # 8 可以获取计算机的CPU个数
    start_time = time.time()
    p_list = []
    for i in range(8):
        p = Process(target=work)
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()
    print('总耗时:%s' % (time.time() - start_time))
    总耗时:0.19758033752441406
        
# 多线程       
from threading import Thread
from multiprocessing import Process
import os
import time

def work():
    res = 1
    for i in range(1, 10000):
        res *= i

if __name__ == '__main__':
    # print(os.cpu_count())  # 8 可以获取计算机的CPU个数
    start_time = time.time()
    p_list = []
    for i in range(8):
        p = Process(target=work)
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()
    t_list = []
    for i in range(8):
        t = Thread(target=work)
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print('总耗时:%s' % (time.time() - start_time))  
    总耗时:0.322171688079834
 """
   计算密集型
     多进程
       0.19758033752441406
     多线程
       0.322171688079834
   所以多进程好
 """

IO密集型

# 多线程
from threading import Thread
import time
def work():
    time.sleep(2)  # 模拟纯IO操作

if __name__ == '__main__':
    start_time = time.time()
    t_list = []
    for i in range(100):
        t = Thread(target=work)
        t.start()
    for t in t_list:
        t.join()
    print('总耗时:%s' % (time.time() - start_time))
 # 总耗时:0.011942148208618164

# 多进程
def work():
    time.sleep(2)

if __name__ == '__main__':
    start_time = time.time()
    p_list = []
    for i in range(100):
        p = Process(target=work)
        p.start()
    for p in p_list:
        p.join()
    print('总耗时:%s' % (time.time() - start_time))
    # 总耗时:0.5508136749267578
"""
 IO密集型
   多线程
     0.011942148208618164
   多进程
     0.5508136749267578
  结论:
    多线程更好
"""

死锁现象

acquire()
release()

from threading import Thread,Lock
import time

mutexA = Lock()  # 产生一把锁
mutexB = Lock()  # 产生一把锁


class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()

    def func1(self):
        mutexA.acquire()
        print(f'{self.name}抢到了A锁')
        mutexB.acquire()
        print(f'{self.name}抢到了B锁')
        mutexB.release()
        print(f'{self.name}释放了B锁')
        mutexA.release()
        print(f'{self.name}释放了A锁')

    def func2(self):
        mutexB.acquire()
        print(f'{self.name}抢到了B锁')
        time.sleep(1)
        mutexA.acquire()
        print(f'{self.name}抢到了A锁')
        mutexA.release()
        print(f'{self.name}释放了A锁')
        mutexB.release()
        print(f'{self.name}释放了B锁')

for i in range(10):
    obj = MyThread()
    obj.start()
    # 出现死锁现象

"""
锁不能轻易使用并且我们也不会自己去处理锁,因为都是拿别人封装的工具
"""

信号量

# 信号量在不同的体系里面 展现出来的功能是不一样的
在并发编程中信号量的意思就是多把互斥锁
在django框架中信号量的意思就算达到某个条件自动触发特定的功能
'''
将自定义互斥锁比喻成豪华的个人卫生间
信号量就相当于公共厕所 里面有多个位置
'''
from threading import Thread, Semaphore

event事件

from threading import Thread,Event

event = Event() # 类似于打造了一个红绿灯

进程池与线程池

"""
  服务端必备的三要素
      1、24小时不间断提供服务
      2、固定的IP和port
      3、支持高并发
"""
TCP服务端实现并发
  多进程: 来一个人客户端开一个进程
  多线程: 来一个客户端开一个线程
    
进程和线程能否无限制的创建 不可以
因为硬件的发展赶不上软件 有物理极限 如果我们在编写代码的过程中无限制的创建进程或者线程可能会导致计算机奔溃
    
计算机硬件是有物理极限的,我们不可能无限制的创建进程和线程
解决方法:
   """ 池:
       降低程序的执行效率 但是保证了计算机硬件的安全
    进程池:
        提前创建好固定数量的进程供后续程序的调用 超出则等待
    线程池:
        提前创建好固定数量的线程供后续程序的调用 超出则等待
        
 当任务超出了池子里面的最大进程或线程数, 就原地等待
 进程池和线程池其实降低了程序的运行效率, 但是它保证了硬件的安全
    """
# 代码
# 线程池
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time
from threading import current_thread

pool = ThreadPoolExecutor(5)  # 线程池线程数默认是CPU的五倍,也可以自定义

def task(n):
    time.sleep(3)
    print(n)
    print(current_thread().name)  # 线程最大数为4
    

def func(*args, **kwargs):
    print(args, kwargs)


'''让异步提交自动提醒>>>:异步回调机制'''
if __name__ = '__main__':
    for i in range(10):
        pool.submit(task, i).add_done_callback(func)
"""
 add_done_callback当任务有结果的时候, 自动调用括号内的函数处理
"""

# 进程池
pool = ProcessPoolExecutor(5)  # 进程池进程数默认是CPU个数 也可以自定义
'''代码执行之后就会立刻创建五个等待工作的进程'''
pool.submit(task, i).add_done_callback(func)

协程

"""
进程:资源单位
线程:执行单位
协程:单线程下实现并发(效率高)
	在代码层面欺骗CPU 让CUP就觉得我们的代码里面没有IO操作
	实际上IO操作被我们自己写的代码检测 一旦有 立即让代码执行别的
	从而最大幅度的占用CPU
	(该技术完全是程序员自己弄出来的 名字也是程序员自己起的)
		核心:自己写代码完成切换+保存状态
"""
import time
from gevent import monkey;monkey.patch_all() # 固定编写 用于检测所有的IO操作(猴子补丁)
from gevent import spawn

def func1():
    print('func1 running')
    time.sleep(3)
    print('func1 over')
    
def func2():
    print('func2 running')
    time.sleep(5)
    print('func2 over')
    
if __name__ == '__main__':
    start_time = time.time()
    # func1()
    # func2()
    # print(time.time() - start_time)
    # 8.01237154006958
    s1 = spawn(func1) # 检测代码 一旦有IO自动切换(执行没有IO的操作 变向的等待IO结束)
    s2 = spawn(func2)
    s1.join()
    s2.join()
    print(time.time() - start_time)
    # 协程 5.015487432479858

MySQL基础

存取数据的演变史

1.文本文件
	文件路径不固定 数据格式不统一
2.软件开发目录规范
	规定了数据应该保存在db目录下>>>:路径偏向统一
3.数据库服务
	统一路径 统一操作方式
    降低学习成本 提高开发效率

数据库软件应用史

1.单机游戏
	数据存储于各个计算机本地 无法共享
2.网络游戏
	数据存储于网络中 可以共享(数据库服务)
"""
数据库服务集群:提升数据的安全性
"""

数据库的本质

1.站在底层原理的角度
	数据库指的是操作数据的进程(一堆代码)
2.站在实际应用的角度
	数据库指的是可视化操作界面(一些软件)
ps:以后不做特殊说明的情况下将数据库其实指的是数据库软件
    
数据库软件本质也是CS架构程序
	意味着所有的程序员其实都有资格编写一款数据库软件

数据库分类

# 关系型数据库
	特征1:拥有固定的表结构(字段名 字段类型)
        id name pwd
    特征2:数据之间可以建立数据库层面关系
        用户表数据
        学生表数据
    MySQL、Oracle、MariaDB、PostgreSQL、sql server、sqlite、access
1.MySQL:开源免费 使用最广 性价比高
2.Oracle:收费 使用成本高但是安全性也最高
3.PostgreSQL:开源免费 支持二次开发 兼容性极高
4.MariaDB:跟MySQL一个作者 开源免费
5.sqlite:小型数据库 主要用于本地测试
    
# 非关系型数据库
	特征1:没有固定的表结构 数据存储采用K:V键值对的形式
         {'name':'jason'}
    特征2:数据之间无法建立数据库层面的关系
        	可以自己编写代码建立逻辑关系
    redis、mongoDB、memcache
1.redis:目前最火 使用频率最高的非关系型数据库(缓存数据库)
    虽然缓存数据库是基于内存做数据存取但是拥有持久化的功能
2.mongoDB:文档型数据库 最像关系型数据库的非关系型数据库
    主要用在爬虫以及大数据领域
3.memcache:已经被redis淘汰

SQL与NoSQL

数据库服务端支持很多的客户端来链接使用
	数据库自带的客户端 Python代码编写 Java代码编写...支持很多语言
想要让服务端兼容诸多客户端 实现正常交互
	1.让服务端识别并自动切换对应语言
    2.统一的标准规范
    比较之下方式2更合理:SQL语句和NoSQL语句
        
SQL语句:
    与关系型数据库交互的语言
NoSQL语句:
    与非关系型数据库交互的语言

MySQL简介

# 版本问题
5.6:使用最为广泛的稳定版本
5.7:目前正在逐步过渡使用的版本
8.0:最新版本,暂时不投入正常生产的环境使用
    
# 下载使用
官网:https://www.mysql.com/
1.点击步骤:
downloads
(GPL) Downloads
MySQL Community Server
Archives
选择版本和系统(以5.6.49为例)
点击下载对应的zip压缩包即可
mac和linux参考下列博客
# linux: 
https://www.cnblogs.com/Dominic-Ji/p/15124625.html
# mac: 
https://www.cnblogs.com/Dominic-Ji/articles/15402755.html
2.解压处理
建议压缩到D或者E、F盘的根目录方便查找
mysql-5.6.44-winx64.zip  >>>  mysql-5.6.44-winx64
    
# 目录结构
bin文件夹
mysqld.exe		服务端
mysql.exe		客户端
'''学习阶段服务端在本地启动即可'''
data文件夹        存放数据
my-default.ini文件  默认配置文件
README文件         说明书

MySQL基本使用

必须先启动服务端 再启动客户端链接
以E:\mysql-5.6.44-winx64为例
    
1.以管理员身份运行cmd
	切换到bin路径下
    E:
    cd mysql-5.6.44-winx64\bin
2.启动服务端
	mysqld
# 维持cmd窗口不要关闭 重新打开一个新的cmd窗口
3.启动客户端链接服务端
先切换到bin路径下
	E:
    cd mysql-5.6.44-winx64\bin
    然后直接输入mysql即可登陆客户端
    '''不带用户名和密码 是游客模式(只能体验基本功能)'''

系统服务的制作

# 针对不想切换路径,直接输入命令的解决措施就是添加环境变量
将E:\mysql-5.6.44-winx64\bin添加到系统环境变量
# 针对不想启动服务端,设置成开机自启解决措施就是编写固定的指令即可
1.清空之前打开的cmd窗口 一定要把之前用cmd启动的服务端关闭(ctrl+c)

2.将mysql添加到系统服务中
	1.如何查看系统服务
    	鼠标右键任务栏选择服务
     	cmd输入services.msc回车	
 	2.以管理员身份打开cmd窗口
    	mysqld --install
        
3.首次添加不会自动启动 需要人为操作一下
	1.鼠标右键点击启动
 	2.命令行启动
    	net start mysql
        
4.关闭所有的cmd 随意打开一个cmd窗口 
  	输入mysql即可链接到服务端
    
    
"""
如果想卸载重新按照
	1.先关闭服务端
		net stop mysql	
	2.移除系统服务
		mysqld --remove
"""

密码相关操作

1.修改密码
	方式1:mysqladmin 
		mysqladmin -u用户名 -p原密码 password 新密码
	方式2:直接修改存储用户数据的表
	方式3:冷门操作 有些版本可能还不支持 
       set password=password('新密码')  # 修改当前登录用户的密码
     
2.忘记密码
	方式1:卸载重新装
  	方式2:把data目录删除 拷贝同桌的目录
 	方式3:小把戏操作
		1.关闭正常的服务端
   		2.以跳过授权表的方式重启服务端(不校验密码)
    	3.以管理员身份进入然后修改mysql.user表数据即可
   			net stop mysql
          mysqld --skip-grant-table
          mysql -uroot -p
          update mysql.user set password=password('123') where Host='localhost' and User='root';
  		4.关闭服务端 然后以正常方式启动即可

数据库重要概念

库:就相当于是文件夹
表:就相当于是文件夹里面的文件
记录:就相当于是文件夹里面的文件中的一行行数据
    
验证
	1.查看所有库的名称:
        show databases;
    2.查看所有表的名称:
        show tables;
    3.查看所有的记录
    	select * from mysql.user;

基本的SQL语句

SQL语句必须以分号结尾
SQL语句编写错误之后不用担心 可以直接执行报错即可

# 库

创建库
create database 库名; # 查看所有库名

查看库
show create database 库名; # 查看指定库信息

编辑库
alter database 库名 charset='utf8' # 修改字符编码

删除库
drop database 库名;

'''
表是存放在库下面 所以操作表之前应该先确定是在哪个库
select database();
结果如果是NULL就是没有切换到任何库下面
切换指定库下:
	use 库名;
在操作时,MySQL默认自带的都不要动
'''

#表

创建表
create table 表名(字段名 字段类型);

查看表
show tables; # 查看所有表
show create table 表名; # 查看指定表信息
desc 表名; # 查看表结构

编辑表
alter table 表名 rename 新表名;

删除表
drop table 表名;


# 记录

查询数据
select * from 表名; # 查看表里面所有的数据
select * from 库名.表名; # 查看指定库下面的制定表的所有数据
select 指定字段 from 库名.表名; # 指定指定字段

插入数据
insert into 表名 values(值1,值2); # 增加单条数据
insert into 表名 values(值1,值2),(值3,值4); # 增加多条数据

编辑数据
update 表名 set 字段名=新数据 where 筛选条件;

删除数据
delete from 表名; # 如果不加筛选条件就是删除所有的数据
delete from 表名 where 筛选条件;

字符编码与配置文件

# 查看MySQL相关信息
	\s  
    当前用户、版本、编码、端口
    
MySQL5.6及之前的版本编码需要人为统一 之后的版本已经全部默认统一

# 如果想要永久修改编码配置 需要操作配置文件
默认的配置文件是my-default.ini

步骤1:拷贝一份 my-default.ini 配置文件,并修改名称为my.ini

步骤2:清空 my.ini 文件内的内容
    
步骤3:添加固定配置信息
    [mysqld]
        character-set-server=utf8mb4
        collation-server=utf8mb4_general_ci
    [client]
        default-character-set=utf8mb4
    [mysql]
        default-character-set=utf8mb4
        
步骤4:保存并重启服务端就可以了
    net stop mysql
    net start mysql

    
ps:
    1.utf8mb4能够存储表情 功能更强大
    2.utf8与utf-8是有区别的 MySQL中只有utf8
修改了配置文件中关于[mysqld]的配置 需要重启服务端
"""
利用配置文件我们可以偷懒
	将管理员登录的账号密码直接写在配置文件中 之后使用mysql登录即可
	[mysql]
		user='root'
		password=123
"""

数据库存储引擎

# 存储引擎的含义
	数据库针对数据采取的多种存取方式
    
# 查看常见的存储引擎方式
	show engines;
    
# 需要了解的引擎
	MyISAM
    	MySQL5.5之前的默认存储引擎
        存取速度快 但功能少 安全性低
    
    InnoDB
    	MySQL5.5之后默认的存储引擎
        支持事务、行锁、外键等操作 存取速度没有MyISAM快 但安全性更高
        
    Memory
    	基于内存存取数据 仅用于临时表数据存取
        
    BlackHole
    	任何写进去的数据都会立刻消失

创建表的完整语法

create table 表名(
	字段名 字段类型(数字) 约束条件,
	字段名 字段类型(数字) 约束条件
);
1.字段名和字段类型是必须的
2.数字和约束条件是可选的
3.约束条件也可以写多个 空格隔开即可
4.最后一行结尾不能加逗号

字段类型之整形

tinyint		1bytes		正负号(占1bit)
smallint	2bytes		正负号(占1bit)
int			4bytes		正负号(占1bit)
bigint		8bytes		正负号(占1bit)

# 注意事项
1、需要考虑正负数的问题, 如果需要存储负数则需要占一个比特位
2、手机号如果使用整型存储, 需要使用bigint才可以
"""
 工作小技巧:
   有时候看似需要使用数字类型存储的数据其实可能使用的是字符串、
     应为字符串可以解决不同语言对数字不精确的缺陷
"""

验证整型默认是否携带正负号
	create table t5(id tinyint);
	insert into t5 values(-129),(128);
结果是-128和127 也就意味着默认自带正负号
	
我们也可以取消正负号
	create table t6(id tinyint unsigned);
 	insert into t6 values(-129),(128),(1000);

严格模式

当我们在使用数据库存储数据的时候 如果数据不符合规范 应该直接报错而不是擅自修改数据 这样会导致失真(没有实际意义)
	正常都应该报错 但是我们之前不小心改了配置文件
    
show variables like '%mode%';

1.临时修改
	set session sql_mode='strict_trans_tables';
    	在当前客户端有效
 	set global sql_mode='strict_trans_tables';
    	在当前服务端有效
        
2.永久修改
	直接修改配置文件

字段类型之浮点型

float(255,30) 
double
decimal
上述浮点型从上往下精确度越来越高
float(m, d)	    4字节,单精度浮点型,m总个数,d小数位
float(255,30)   总共255位 小数位占30位

double(m, d)	8字节,双精度浮点型,m总个数,d小数位
double(255,30)  总共255位 小数位占30位

decimal(m, d)	decimal是存储为字符串的浮点数
decimal(65,30)  总共65位 小数位占30位

# 实操
create table t7(id float(255,30));
create table t8(id double(255,30));
create table t9(id decimal(65,30));

insert into t7 values(1.111111111111111);
insert into t8 values(1.111111111111111);
insert into t9 values(1.111111111111111);

"""
 使用范围:
   正常业务精确度只要小数点三四位的样子的时候,使用float就可以
   如果是科研业务,精确度要求极高,那么就使用decimal
"""
三者的核心区别在于精确度不同
	float	<	double  < 	decimal

字段类型之字符类型

# 定长
char
char(4) # 最多存储四个字符 超出就报错 不够四个空格填充至四个

# 变长
varchar
varchar(4) # 最多存储四个字符 超出就报错 不够则就有几位存几位

数字的含义

字段类型括号内的数字大部分情况下是用来限制存储的长度
但是咋整形中并不是用来限制长度的,而是用来控制展示长度的

字段类型之枚举与集合

# 枚举
	多选一模式
    create table t15(
    id int,
    name varchar(32),
    gender enum('male','femle','others')
    );
    
    insert into t15 values(1,'tony','男'); # 报错
    insert into t15 values(2,'jason','male'); # 正确
'''
 插入数据的时候,正对gender只能填写提前定义好的数值
''' 
# 集合
	多选多(也可以多选一)
    create table t16(
    id int,name varchar(32);
    hobbies set('read','study','sleep')
    );
    
    insert into t16 values(1,'jason','read')
    insert into t16 values(2,'tony','study')
    insert into t16 values(3,'tom','read,study')

字段类型之日期类型

datetime		年月日时分秒
date			年月日
time			时分秒
year			年

create table t17(
	id int,
  	name varchar(32),
 	register_time datetime,
 	birthday date,
 	study_time time,
 	work_time year
);
insert into t17 values(1,'jason','2000-11-11 11:11:11','1998-01-21','11:11:11','2000');
ps:以后涉及到日期相关字段一般都是系统自动回去 无需我们可以操作

MySQL字段约束条件

# 字段类型与约束条件的关系
约束条件是基于字段类型之上的额外限制
	eg:id int unsigned
id int 字段类型int规定了id 字段只能存整数
约束条件unsigned指在整数的基础上还必须为正数

无符号、零填充

# 无需正负号
unsigned
	id int unsigned
    
# 零填充
zerofill
	id int(5) zerofill

空与非空

# 空
null

# 非空
not null

默认值

default

唯一值

unique

主键

primary key

自增

auto_increment

外键关系

表关系、数据关系其实意思是一样的 只是说法上有区分

# 关系种类
1.一对多
2.多对多
3.一对一
4.没有关系
'''
关系的判断的关键技巧就是:换位思考
'''

外键的建立

小技巧:先定义出含有普通字段的表 之后再考虑外键字段的添加
 
# 普通 被关联
create table dep(
	id int primary key auto_increment,
    dep_name varchar(32),
    dep_desc varchar(64)
);

# 关联 外键    
create table emp(
	id int primary key auto_increment,
    name varchar(32),
    age int,
    dep_id int,
    foreign key(dep_id) references dep(id)
);

SQL语句查询关键字

# 查询
select 
	指定需要查询的字段信息
select * 
	查看所有字段
select name
	查看name字段
select char_length(name)
	支持对字段做处理
    
# 指定
from
	指定查询的表信息
    from mysql.user
    from t1
 
SQL语句中关键字的执行顺序和编写顺序并不是一致的 可能会错乱
	eg:
    	select id,name from userinfo;
我们先写select再写的from 但是执行的时候是先执行的from再执行select

'''
对应的关键字编写顺序和执行顺序没必要过多在意 熟练后会非常自然的编写
只需要把注意力放在每个关键字的功能上即可
'''

查询关键字

where # 筛选
group by # 分组
having # 过滤
distinct # 去重
order by # 排序
limit # 分页
regexp # 正则表达式

多表查询思路

select * from emp,dep;  会将两张表中所有的数据对应一遍
这个现象我们也称之为'笛卡尔积' 无脑的对应没有意义 应该将有关系的数据对应到一起才合理
基于笛卡尔积可以将部门编号与部门id相同的数据筛选出来
涉及到两张及以上的表时 字段很容易冲突 我们需要在字段前面加上表名来指定
select * from emp,dep where emp.dep_id=dep.id;
基于上述的操作就可以将多张表合并到一起然后一次性获取更多的数据

原文地址:http://www.cnblogs.com/super-xz/p/16929987.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性