zoukankan      html  css  js  c++  java
  • SQL金典

    ps:补充自己的基础知识,大神请无视..

    ~~~~~~~~~~~~~~~~~~~~~

    DataBase Management System,DBMS。。。。
    Catalog 。。。库
    Table。。。。表
    Column。。。列--Field 字段,每个列描述数据的一个特性。
    DataType 。。。数据类型
    Record。。。。记录---Row行,
    PrimaryKey。。。主键-----多个字段才唯一标识一列时,称为复合主键
    Index 。。。索引-不建立索引是全表扫描,速度慢;建立索引只扫描索引,速度快;
        缺点:占据一定磁盘空间,减慢了插入和删除速度(更新索引);
    表关联:两张表通过字段关联,关联到其他表的主键的字段称为 外键;
    SQL的4个功能:创建库并定义表结构,查询数据,更新、删除指定数据,控制数据库安全。
    1、入门

     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    1、数据类型
        整型、数值类型、
        字符相关类型(固定长度char、可变长度varchar、多语言可变长度nvarchar、可变长度字符串text、ntext可变大字符)、
        日期时间类型datetime/smalldatetime/timestamp时间戳、
        二进制类型:图片、视频等,非常大的,没有固定结构的数据,设置和读取也需要宿主语言的辅助。如 image(MS sqlServer),其他是blob。
        
    2、通过SQL 管理数据表
        创建表 create table name{
            字段名1 字段类型, 
            字段名2 字段类型,
             .....
            约束定义1,
            约束定义2,
            .....
            }
        定义非空约束,在类型定义后增加 NOT NULL ,
        定义默认值,------------增加 DEFAULT ,
        定义主键,在所有字段定义之后, PRIMARY KEY(字段名),
        联合主键:两个字段联合起来作为主键,(复合主键),PRIMARY KEY(字段名1,字段名2),
            缺点:    效率低,增删改查都需要处理两个字段,大大降低了数据处理速度,
                结构糟糕,联合主键会有业务含义,与“使用逻辑主键不是业务主键”的最佳实践冲突,开发和维护麻烦,
                外键麻烦或无法创建,
                开发难度很大,工具和框架对单主键支持良好,对多主键复杂特殊处理。
        定义外键:所有字段之后,FOREIGN KEY 外键字段名 REFERENCES 目标表名(被关联的字段名)
        修改已有数据表:    ALTER TABLE 待修改的表名 ADD 字段名 字段类型 
                ALTER TABLE 待修改的表名 DROP 待删除的字段名            
        删除数据表 DROP table 表名
    
        
    2、数据表的创建和管理

     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    insert into tableName(A,B,C) values(a,b,c)
    insert into tableName(a,b,c) 按照定义表中字段顺序进行插入,不推荐。
    非空值必须插入,主键必须唯一不重复,外键值必须在目标表中存在。--所以不推荐在数据库中生成外键,有程序控制更灵活。
    update tableName set A=a,B=b,C=c 
        where X=x
    非空值不能更新为NULL,主键不能更新为重复,外键不能不存在。
    delete from tableName where X=x 有外键时,必须先删除引用,不然删除失败。
    delete只删除数据,drop 删除数据和表结构。
    3、数据的增删改

     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    select * from tableName where X
    select A,B from tableName where X
     列名 as 别名  ,as 可省略,但要保留空格。
    
    过滤问题:可程序控制,缺点是 全取出对内存网络消耗都大,程序实现复杂,关联其他表的情况不能处理。所以用数据库提供的最好。
    
    数据汇总 
    聚合函数 MAX MIN AVG SUM COUNT
    count(*)结果集的总条数,count(列名)  列名的值不为NULL的总记录数,不一定相等。
    order by  A asc/desc, B asc/desc 先A,再B 排序----推荐显式指定排序,防止不同数据库之间差异影响结果。
    
    通配符过滤:
    like 二元操作符,左边为列名,右边为表达式, 
        单字符匹配 下划线 _ ,如 b_d,匹配第一个字符为b,第二个字符任意,第三个字符为d的字符串。
        多字符匹配 百分号 % , 如 like%abc%’.
        可一起使用,如 like '%n_'
    集合匹配 只MS SQL Server 支持,方括号[] ,与字符集中任意一字符想匹配的字符, 如 [bt],有点像..正则表达式啊?
        还可以使用否定符取反,[^bt],匹配不是bt的串,
        在其他库上可用 or语句实现。
        缺点:效率低,不要过多使用。
    空值检测  select A,B,C from tableName where X is/is not NULL
    反义运算符 ! 作用于运算符的取反,只有MS SQL 和DB2支持,
        NOT 作用于表达式的取反, NOT(表达式),推荐使用。
    多值检测  or或 inIN(值1,值2,值3....)
    范围值检测  < >between and, 字段名 between leftValue and rightValue ,包括范围边界值。性能好,优先考虑。
    低效的where 1=1 :数据库系统无法使用索引等查询优化策略,只能每行数据进行扫描(全表扫描),大大降低了性能。
    
    数据分组:用来将数据分为多个逻辑组,每个组是所有记录的一个子集,从而对每组进行聚合运算。Group by 分组字段。一般放在语句最后。 
        分组语句必须和聚合函数一起使用?又可以分开使用?
        需要分组的所有列,都必须位于group by子句列名列表中,没有出现的列,不能放在select语句后的列名列表中。
            select A,B from tableName group by A ,是错误的,A分组了,但B没有,不一样的B但一样的A的无法显示。
            select A,sum(B) from tableName group by A,正确,聚合函数得出一样的B值,就能显示。
            很多列时是 逐层分组,组中组,结果集是以最末一级分组来进行输出的。
        列:select A,B,count(*) as M from tableName group by A,B order by A
    Having语句 对部分分组的过滤,
        聚合函数不能用于where语句,改为having即可,having 可使用复杂的过滤条件,orand in 等。
        语法和where几乎一样,只是和group by的位置不一样,where在group by 之前,having 在group by 之后,
        having语句不能包含未分组的列名,
        应该能同时用吧?
    
    限制结果集行数 只检索结果集中的部分行,主流数据库都支持,但差异很大。
        MySQL  关键字 limit 放在select语句最后 ,limit 首行行号, 要返回结果集的最大数目   --行号从0开始
            例子: select * from tableName order by X desc limit 2,5
        SQLServer2000 关键字TOP NUM  结果集中的前N条记录,用子查询实现区间范围功能,
            例:select top 3 * froom tableName
                where A NOT IN 
                    ( select top 5 A from tableName order by X desc)
                order by X desc --查询按X排序的第6开始的3条结果。
        SQLserver2005 兼容2000,另外还有窗口函数 row_number(),计算每一行数据在结果集中的行号(从1开始),
            语法:row_number() over(排序规则)    --只出现在select或order by 子句中
            例:(select row_number() over(order by A) as rownum,A,B,C,D from tableName ) as M
            配合子查询使用 
                select * from M where rownum >=3 and rownum<=5
        Oracle 窗口函数 row_number(),与sqlserver2005一样,但是不用 as定义别名,
            另外:Oracle为每个结果集都默认增加行号的列rownum,所以前N条记录可以用 where rownum<=N 实现,
            但是 取中间值必须用窗口函数,因为Oracle会把不符合的剔除结果集,后面的rownum会自动减一,一致都不满足。
        DB2 窗口函数支持,还有关键字 Fetch,用来提取前N行,放在order by后面,
            例:select * from tableName order by X desc fetch first 6 rows only
            可用fetch配合子查询实现区间。
        数据库分页    核心就是 限制结果集行数
            每页数据条数 PageSize,当前页(从0开始计数)CurrentIndex, 一次只查询从P*C开始的P条数据。
    
    抑制数据重复    distinct 关键字是对整个结果集进行数据重复抑制的,不是针对一列。
    
    计算字段:数据默认展现方式不完全符合应用要求时,经计算、转换、格式化等再使用,比用宿主语言处理性能高很多。
        常量字段 值确定的一个值作为字段,可用as 。
        字段间计算,加减乘除等,可用于where子句,
        数据处理函数 
            字符串长度,length,(在ms sql server中是len)
            字符串子串 substring(Oracle和DB2中是substr),
            字符串连接 
                MYSQL会把+ 转化为数值,不能用,应该用函数 concat(),concat_ws()可加入指定分隔符。
                MS SQL Server 用+,
                Oracle 使用|| 双竖线,也提供concat(),
                DB2 双竖线 || ,和concat()。
    
    计算字段的其他用途: 数据过滤、删除、更新中,都可以使用计算字段。
    
    不从实体表中取的数据:
        MYSQL和MS SQL Server 允许使用不带FROM子句的select语句来查询 不属于任何实体表的数据,
            例: select 1    /select length('abc') 
        Oracle不允许,但可以使用系统表来作为from子句,常用DUAL。
            例: select 1,length('abc') from DUAL
        DB2 的系统表是 SYSIBM.SYSDUMMY1
    
    联合结果集:    UNION 两个完全不同的查询结果集的组合,显示在一个结果集中。相当于select 语句+起来,一般用于各种报表。
        select A,B,C from table1 
        Union select X,Y,Z from table2
        原则:结果集的列数相同,不同时补常量字段;对应列的类型相容,相同或者能转换为同一类型--推荐类型完全相同。
        Union 会把完全重复的数据合并为一条,(自带distinct啊...),不需要合并的使用Union all.
    
            
            
                
    4、数据检索

     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    数学函数 
        绝对值 ABS(),指数power(),平方根sqrt(),
        随机数    select rand()--Mysql,
            select rand(随机数种子) --MS SQL server,
            select dbms_random.value from dual --Oracle没有内置随机数函数
            还有 dbms_random.value(low,high) ,dbms_random.normal正态分布的一组数,偏差1,期望为0
            dbms_random.string(opt,len)随机字符串。
            select SYSFUN.rand() from sysibm.sysdummy1 --DB2.
        Round()四舍五入
        圆周率π, PI(),Oracle等不支持的用 ACOS(-1)代替:-1的反余弦值等于π值。
        求符号:SIGN(),大于0,则1,小于0,则-1,等于0,则0.
        求整除余数:MOD(),--MS SQLserver中为 操作符%.
        自然对数: LOG()  --Oracle中为 LN().
            LOG10() 计算一个以10为底的对数值 --Oracle中为LOG(m,n),以m为底n的对数。
        Power(X,Y)用来计算X的Y次幂。
    
    字符串函数:
        长度:length(),----或len(),
        小写:lower(),---DB2中为 Lcase().
        大写:Upper(),---DB2中为Ucase().
        截去左侧空格:LTRIM(),右侧空格:RTRIM(),两侧空格:TRIM()或者组合左右实现。
        子串:substring(S,start,length),substr().
        计算子串位置:Instr(string,substring),不在返回0,---MS SQL server中为charindex,---DB2中为locate(subs,S).
        从左侧取子串:left(s,length),从右侧取子串:right(),
        字符串替换:Replace(S,tobeS,toS),toS是空的话就是删除功能。
        得到字符的ASCⅡ码:ASCⅡ(), 反过来是 CHAR(),--Oracle中为CHR(),
        发音匹配:soundex()计算发音特征值,返回4个字节的字符串,第一个字符总是初始字符串的第一字符,后面是3位数字。
            difference()--MS sql server和DB2中额外提供的函数。
    
    日期时间函数: 
        类型有4种 日期Date、时间Time、日期时间DateTime、时间戳TimeStamp。
        一般字符串可自动转化为对应类型,但Oracle需要函数To_Date(),
        当前日期时间 
            MySQL  NOW(), ---等同于 SYSDATE()、CURRENT_TIMESTAMP,
                   CURDATE()日期, CURRENT_DATE.
                   CURTIME()时间,
            MS SQL SERVER
                getdate(),配合convert()使用。
                select convert(varchar(50),getdate(),101) as 当前日期,
                select convert(varchar(50),getdate(),108) as 当前时间,
            Oracle  使用系统表 DUAL中查询SYSTIMESTAMP来得到当前时间戳,SYSDATE得到日期时间,
                配合TO_CHAR(时间日期值,'YYYY-MM-DD'),TO_CHAR(时间日期值,'HH24:MI:SS')。
            DB2 系统表SYSIBM.SYSDUMMY1中的 CURRENT TIMESTAMP/DATE/TIME。
        日期增减  MS SQL Server 中 DATEADD(datepart,number,date)
        日期差额 MS SQL Server 中 DATEDIFF(datepart,startdate,enddate)返回以datepart为单位的差额
            例:select DATEDIFF(S,convert(varchar(50),getdate(),101),getdate())--今天过了多少秒。
        计算日期是星期几:
            MYSQL dayNAME()
            MS SQL server : select datename(dw,getdate()), --dw 工作日,
            Oracle: TO_CHAR(DATE,format)--day 会返回周几
        取得日期特定部分: MS SQL中 DATENAME() 和DATEPART(),
    
    其他函数:
        类型转换,尽量显式转换,避免隐式转换。
            MYSQL 中 CAST(expression as type)和Convert(ex,type),
            MS SQL server,CAST(expression as type)和Convert(type,ex)。
        空值处理:
            coalesce(表达式,value1,value2...),返回所有参数中第一个非空表达式,
            coalesce()的简化版,两个参数
                IFNULL(EX,value)--MYSQL
                ISNULL(ex,value)--MS SQL Server
                NVL(ex,value)--Oracle
            NULLIF(ex1,ex2) 如果表达式不等价,返回ex1的值,如等价,返回ex1类型的空值。
        CASE函数:
            用法1, case expression
                    when value1 then returnvalue1
                    when value2 then returnvalue2
                else defaultreturnvalue
                end
            用法2,case 
                    when condition1 then returnvalue1
                    when...
                else defaultreturnvalue
                end    --只能对一个表达式进行判断。
    各数据库系统独有函数:
        MS SQL server ,辅助函数 app_name()返回当前回话的应用程序名称;
                current_user 当前登录用户名
                host_name()返回工作站名。
                newid()生成全局唯一字符串,
                
            
                
                
    函数

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    1、索引 针对字段,必须指定字段,可以为多字段创建一个索引,
        创建表 create table t_person(
        fnumber varchar(20), fname varchar(20), fage int)
        创建索引 create index 索引名 on 表名(字段1,字段2,...)
        create index idx_person_name on t_person(fname)
        删除索引用 drop index 表名.索引名
    2、约束 非空 NOT NULL、
        唯一 Unique约束 防止一个特定列中两个记录具有同样的值,分为单字段唯一与复合唯一
            单字段唯一的 语句是 字段后加 UNIQUE--该字段不能有重复值
            复合唯一是 constraint 约束名 unique(字段1,字段2...)--字段1和字段2,单个可以重复,但是不能同时重复。
            在已经创建好的表上添加新约束 alter table 表名 add constraint 约束名 unique(字段1,..)
                    删除约束 alter table 表名 drop constraint 约束名
        CHECK约束 检查输入到记录中的值是否满足一个条件, 任意有效的SQL表达式,
             例: age int check(age>0), number varchar(20) check (length(number)>12)
            如CHECK子句要使用其他列,则在create table末尾使用 constraint关键字定义。
            constraint 约束名 check(条件),
            例:create table t1(A INT, B INT,C INT,  Cconstraint ck_AB Check(A<B))
        主键约束 唯一标识,不空,PRIMARY KEY,
        外键: 语法,foreign key 外键字段 references 外键表名(外键表的主键字段)
            或 alter table tName add constraint fk_A_B 
                foreign key (外键字段) references 外键表名(外键表的主键字段)
    6、索引与约束

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    join类型: 交叉连接(cross join)、内链接(inner join)、外连接(outter join),部分数据库系统还支持联合连接(union join)。
    1、内连接:语法 inner join tableName on condition --进行连接时的条件,
        例:select A,B from table1 
            inner join table2  on table1.M=table2.N where table1.X=x 
        inner 是可选的,默认就是内连接。
    2、不等值连接:连接的条件中可以使用< > <> 等运算符,以及like between and,和函数。
        不等值连接是 2个表的笛卡尔运算,一般需配合等值连接匹配条件使用。
    3、交叉连接:所有表所有记录包含在结果集中,不存在on子句,分隐式和显式连接。
        隐式: select t1.A,t2.B from t1,t2
        显示: select t1.A,t2.B from t1 cross join t2。 一般只用隐式连接。
    4、自连接:表与自身连接,通常需处理的问题是 一个记录和自己相同,或者A与B相同时B也与A相同的问题。会写成 o1.id<o2.id.
    5、外部连接:主要用来解决空值匹配的问题,不需要两个表具有匹配记录,这样可以指定某个表中的记录总是放到结果集中。
        分为3种类型:右外 right outer join,左外left outer join,全外full outer join。
            左外返回左表中部复合连接条件的数据,右外返回右表中,全外是两个合集。--以关键字join分左右。
        
        
        
    7、表连接

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    以结果集供其他SQL语句使用,--嵌套内的查询。
    只返回单值的,和返回一个数据集的.
    1、单值的又叫标量子查询,可用于列表、表达式、where等场合
    2、列值子查询,表子查询,可用于from、insert、连接、IN子句等场合。
        select id,name,(select max(X) from B where B.id=A.id) from A 
            --通过where子句,子查询连接到外部的select,不能单独执行。--相关子查询。
    3、集合运算符与子查询
        in 匹配某一项,
        =any 等价于in, <>any 等价于 NOT IN, any不能与固定的集合想匹配,
        All 也需要带比较符,比较的值需要匹配子查询中所有值,不能与固定集合想匹配。
            如匹配集合为空,不论什么比较,ALL都返回true。
        exists 单目运算符,检查每一行是否匹配子查询,只有和相关子查询一起使用。
            select A,B from t1 where exists ( select * from t2 where t2.id=t1.id and t2.X<x)
    4、子查询应用 
        insert into t1(A,B) select A,B from t2   --列序对应。
        A或者B换成 case 子句,可实现 数据处理,
        
    8、子查询

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    1、SQL注入漏洞攻防 :用户在输入中拼接字符串,偶后转入数据库去执行这字符串,造成不可预测影响。 
        过滤敏感字符和使用参数化SQL;
        过滤 or/and/select/delete等关键字,--麻烦且不严谨。
    2、SQL调优 :
        二八原则:找出消耗性能的语句,优化。
        索引:最根本的优化方法,内功! 
            聚簇索引:数据表的物理顺序与索引顺序相同; 字典里拼音和偏旁部首都是索引,前一是聚簇的,
        存储碎片-重建索引,reindex/rebuild ,
        尽量减少全表扫描,创建必要索引,使用预编译查询(参数化SQL)、
        调整where子句连接顺序-DBMS一般采用自下而上的顺序解析WHERE子句,表连接最好写在其他where条件之前,以过滤掉最大数量记录后再连接,
        select中不使用*,尽量压缩SQL到一条语句且一次执行。
        用where 替换 having--后者只会在检索出所有记录后才对结果集过滤,
        使用表别名,前缀每个列,减少解析时间和错误。
        用exists替代IN--in子句执行一个子查询内部的排序和合并,
        用表连接替换exists
        避免在索引列上使用计算--
        使用UNION all 替换union--在确保结果不重时,不实用检索的自动去重功能。
        避免隐式类型转换造成全表扫描--查询条件中使用匹配的类型值,
        防止检索范围过宽--使用is not null 或 不等于判断,可能造成优化器假设匹配记录数太多,或使用like的带 %c 形式,不能有效评估匹配数量。
    3、事务:原子操作,transaction,原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability,简称 ACID特性。
        启动、提交、回滚..制定锁粒度、隔离级别..
        例: set transaction isolation level read uncommited 
            begin transaction
                ....
            commit
    4、自动增长字段: MS SQLserver 中 关键字为 identity(startvalue,step)起始数字,步长。
        业务主键后期维护不方便,逻辑主角不能合并表。
    6、NULL的学问:NULL表示未知,而不是没有值,和任何运算都是NULL,出现在where子句是False, 在聚合函数中会被忽略。
    7、开窗函数: 函数名(列) over(选项) --
        select A,B,COUNT(*) OVER() from t1 where X<x 
        partition by 子句 ,定义行的分区,从而进行聚合计算,创建的分区独立于结果集,位于over的选项内。
        可多次使用,结果互不影响。
        select A,B,COUNT(*) OVER(partition by A),COUNT(*) OVER(partition by B)  from t1.
    8、with子句和子查询:降低使用子查询的次数可以优化性能,
        SQL提供了with子句用于为子查询定义一个别名,一次定义多次使用。
        DRY don't repeat yourself. 
        格式: with 别名 as (子查询) --是SQL语句,不是存储过程,可远程调用。
        还可以定义列别名: with 别名(f1,f2) as (子查询) 
    9、表复制: create table t2 as select * from t1 where 1<>1
           select * into t2 from t1 where 1<>1
    10、高级话题
  • 相关阅读:
    LaTeX入门
    用jdom来解析xml文件小Demo
    Java乔晓松基于注解的面向AOP(切面)编程
    三层架构实战篇—系统登录实例
    selenium ide插件介绍
    WPF17行为(以控件在界面拖动为例)
    火狐浏览器显示“已阻止载入混合活动内容“的解决方法
    博客园—打赏功能
    网页返回顶部的几种方法
    自定义美化博客园
  • 原文地址:https://www.cnblogs.com/dacude/p/4668643.html
Copyright © 2011-2022 走看看