1,数据库的生命周期:
需求分析(需求说明书) -- 逻辑设计(E-R) -- 物理设计(表结构) -- 数据库实现(范式化) -- 数据修改(索引/约束) -- 数据库监控(维护) 详细可参考:http://www.cnblogs.com/samwu/archive/2011/09/07/2169829.html2,E-R图学习:列出一些基本信息,我也是这里学习的 http://www.cnblogs.com/dekevin/archive/2012/07/18/2596745.html3,主键:唯一标识列 特点:字段非空 字段具有唯一性 该值不允许修改(建议|【ps:改还是有办法改的】) 每个实体只能有一个主键(建议|【ps:也可以有联合主键】) 外键:连接不同实体 作用:保持数据完整性4,数据库的三大范式(控制数据的冗余) 第一范式(1NF):确保每列保持原子性 第二范式(2NF): 确保表中的每列都和主键相关 第三范式(3NF): 确保每列都和主键列直接相关,而不是间接相关 详细可参阅:https://www.cnblogs.com/linjiqin/archive/2012/04/01/2428695.html 【PS:博主有话说>>通过故意提供冗余数据,降低连接的复杂度,获取更快的查询时间。 此时,取消规范化也是必须的。 总的来说,性能 > 规范】5,增删改查格式: 增:INSERT INTO 表名(列名) VALUES (值) 删:DELETE FROM 表名 WHERE 条件 【PS:条件要是没加,则删除整张表数据。谨慎操作】 改:UPDATE 表名 SET 字段 = '值' WHERE 条件 【PS:条件要是没加,则修改整张表数据。谨慎操作】 查:SELECT * FROM 表名 WHERE 条件 ========================================== 【PS * : 表示检索指定表中的所有列】6, GROUP BY 子句1:用于分组输出行
ORDER BY 子句2:排序【DESC | ASC】 语句1: --解释:根据name来分组,并且根据name来排序 --【PS:使用group by 时,查询的非聚合函数都要在group by中】 ====================================================== SELECT NAME FROM USERS GROUP BY NAME ORDER BY NAME DESC 7,PIVOT: 将行旋转成列 语句2: ====================================================== SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日] --这里是PIVOT第三步(选择行转列后的结果集的列)这里可以用“*”表示选择所有列,也可以只选择某些列(也就是某些天) FROM WEEK_INCOME --这里是PIVOT第二步骤(准备原始的查询结果,因为PIVOT是对一个原始的查询结果集进行转换操作, --所以先查询一个结果集出来)这里可以是一个select子查询,但为子查询时候要指定别名,否则语法错误 PIVOT ( SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]) --这里是PIVOT第一步骤,也是核心的地方,进行行转列操作。 --聚合函数SUM表示你需要怎样处理转换后的列的值,是总和(sum), --还是平均(avg)还是min,max等等。例如如果week_income表中有两条数据并且其week都是“星期一”, --其中一条的income是1000,另一条income是500,那么在这里使用sum,行转列后“星期一”这个列的值当然是1500了。 --后面的for [week] in([星期一],[星期二])中 for [week]就是说将week列的值分别转换成一个个列, --也就是“以值变列”。但是需要转换成列的值有可能有很多,我们只想取其中几个值转换成列,那么怎样取呢? --就是在in里面了,比如我此刻只想看工作日的收入,在in里面就只写“星期一”至“星期五” --(注意,in里面是原来week列的值,"以值变列")。 --总的来说,SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]) --这句的意思如果直译出来, --就是说:将列[week]值为"星期一","星期二","星期三","星期四","星期五","星期六","星期日"分别转换成列, --这些列的值取income的总和。 )TBL--别名一定要写 ====================================================== 【PS:以下语句as的意思是给列起别名的意思】 ====================================================== 语句3: select [1] as 'v1',[2],[3],[4],[5],[6],[7],[8] from ( select PublisherId from books ) as tb_source pivot( count(PublisherId) for PublisherId in ([1],[2],[3],[4],[5],[6],[7],[8]) ) as tb_pivot8,ROW_NUMBER(): 返回一个唯一的序列号 【ps:要配合over(order by 列名);】 语句4: ========================================================== SELECT ROW_NUMBER() OVER(ORDER BY ID),* FROM Books9,PARTITION BY 子句3:用于将结果集划分为应用了ROW_NUMBER()函数的分区 每个分区的第一行都是从1开始的 语句5: ========================================================== SELECT ROW_NUMBER() OVER(PARTITION BY PublisherId ORDER BY PublisherId) as rownumber,* FROM Books WHERE PublisherId in (1,2,3)10,通配符:% _ [] [^]
语句6:查找用户名以L开头的用户信息 ========================================================== SELECT * FROM USERS WHERE USERNAME LIKE 'L%'11,聚合函数:SUM() --求和
COUNT() --求数量 MIN() -- 最小值 MAX() -- 最大值 AVG() -- 平均数 ROW_NUMBER() -- 获取序列号12,日期函数: CURRENT_TIMESTAMP --2017-11-23 19:11:03.320 GETDATE() --2017-11-23 19:11:03.320 DATEPART(YEAR, GETDATE()) --2017 YEAR(GETDATE()) --201713,表连接: 13.1 内连接: 语法1:SELECT * FROM A INNER JOIN B ON A.ID = B.AID; 语法2:SELECT * FROM A, B WHERE A.ID = B.ID ============================================= 【PS:以下语句是为表起别名,并且查询指定表的指定字段信息】 SELECT a.c1, b.c1 FROM A a INNER JOIN B b ON A.ID = B.AID; ============================================= 13.2 外连接: 13.2.1 左连接:SELECT * FROM A LFET JOIN B ON A.ID = B.AID; 13.2.2 右连接:SELECT * FROM A RIGHT JOIN B ON A.ID = B.AID; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 【PS:左连接 与 右连接 是有区别的,】详情可查看: https://www.cnblogs.com/cy163/archive/2008/10/16/1312920.html ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 13.3 全连接 :SELECT * FROM 表1 FULL JOIN 表2 ON 表1.ID = 表2.表1_ID;14,UNION JOIN :创建一个包含两个表中所有行的表
SELECT * FROM A union JOIN B ON A.ID = B.AID; 等价于: SELECT * FROM A UNION ALL SELECT * FROM B 【PS:两表必须有相同数量的列,对应的数据类型要兼容】15,关于空行:
语句7:(查询用户名不为空的数据行)【IS NULL : 与 IS NOT NULL 相反】 ================================================================= SELECT * FROM USERS WHERE NAME IS NOT NULL 【PS: NAME = NULL 与 NAME IS NULL 是不一样的】语句8:查询用户表中的用户名,若为空,则用‘未知’替代
================================================================= SELECT ISNULL(Name, '未知') FROM USERS16,BETWEEN...AND... / IN() / NOT IN() --范围性条件17,条件逻辑运算符:AND / OR / NOT 18,创建新表1 语句9:创建一个临时表【#temp: 表名加#,表明创建临时表,否则为永久表| 临时表的周期:查询窗口关闭即销毁】 ========================================================== SELECT ID, USERNAME, LOGINID, EMAIL INTO #TEMP FROM USERS 语句10:用途:可以复制一个表结构: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SELECT * INTO USERS_L FROM USERS --复制表结构,同时复制表数据,但是无约束,无主键 SELECT * INTO USERS_L FROM USERS WHERE 1=0 --复制表结构,但是不复制表数据,无约束 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++19,操作数据:
创建表后,插入数据:使用第5点INSERT INTO; 【PS:插入的数据中,有外键列存在的话,则插入的数据在外键表中必须存在,否则插入失败。--[保证数据完整性]】更新数据:
更新一条数据中的多个字段: 语句11: ======================================================== UPDATE A SET NAME='JAKE',LOGINID='10001' WHERE ID = 1删除数据:
语句12: ======================================================== DELETE FROM USERS WHERE ID = 1; 数据量大时,可用:TRUNCATE TABLE 【PS:TRUNCATE不执行日志操作,不支持回复删除的数据】 【网上说使用delete误删除的: 可以使用mdfview程序回复,下载地址:http://www.minisoft.cn/mdfview.rar】 【我没试过...】