第一章: 1.数据库的设计分为三个阶段: 需求分析阶段:分析客户的业务和数据处理需求 概要设计阶段:绘制E-R关系图 详细设计阶段:用数据库的三大范式进行审核,创建数据库和表 2.在E-R关系图中: 矩形表示实体,椭圆表示属性,菱形表示关系,直线用来连接属性和实体 3.数据库的三大范式: 1.第一范式:每列(属性)都是不可再分的最小数据单元,即列不可再分 2.第二范式:确保表中的每列都和主键相关 3.第三范式:不存在传递依赖关系,确保每列都和主键直接相关,而不是间接相关 注意:存在部分依赖不满足第二范式[订单编号,商品编号](组合键) 订单日期与订单编号有关,与商品编号无关 第二章 1.创建一个数据库文件和日子文件 if exists(select * from sysdatabases where name='employees') drop database employees create database employees on primary ( name='employees_data', filename='D:\project\employees_data.mdf', size=10, filegrowth=10% ) , ( 次要数据文件 name='employees_data2', filename='D:\project\employees_data2.ndf', size=20, filegrowth=1 ) log on ( name='employees_log', filename='D:\project\employees_log.ldf', size=10, maxsize=50, filegrowth=1 ) ( name='employees_log2', filename='D:\project\employees_log2.ldf', size=10, maxsize=50, filegrowth=1 ) 2.删除数据库: if exists (select * from sysdatabases where name='stuDB') drop database stuDB 3.创建表: if exists (select * from sysobjects where name='stuInfo') drop table stuInfo create table stuInfo ( 字段1 数据类型 是否为空, 字段2 数据类型 是否为空 ) 4.添加约束: alter table stuInfo add constraint PK_stuNo primary key (stuNo), constraint UQ_stuID unique(stuID), constraint DF_stuAddress default('地址不详') for stuAddress, constraint CK_stuAge check(stuAge between 15 and 40), constraint FK_stuNo foreign key(stuNo) references stuInfo(stuNo) 代码创建组合键: alter table stuInfo add constraint PK_stuNo primary key (stuNo,stuNo2) 5.删除约束: alter table 表名 drop constraint 约束名 6.添加一个新的列: alter table stuInfo add stuBirthday datetime 7.删除一个列: alter table stuInfo drop column stuBirthday 8.创建登录用户: exec sp_grantlogin 'jbtraining\s26301' --window登录用户 exec sp_addlogin 'zhangsan','1234' 创建数据库用户: exec sp_grantdbaccess 'jbtraining\s26301','s26301DBUser' --window登录 exec sp_grantdbaccess 'zhangsan','zhangsanDBUser' 给数据库用户授权: grant create table to s26301DBUser grant select,insert,update on stuInfo to zhangsanDBuser 第三章 1.变量:@表示局部变量,@@表示全局变量 (一般不声明全局变量) declare @name varchar(8) 同时声明两个变量:declare @name varchar(9),@seat int 2.set和select赋值语句区别: set 一次只能给一个变量赋值 select 一次可以给多个变量赋值,select适用于从表中查出数据给变量赋值的情况 注意:select 赋值和查询不能同时进行 3.两种输出语句: print 局部变量或字符串 select 局部变量 as 自定义列名 注意:print 打印语句要求只能以一种数据类型打印 即print '我是的年龄:'+convert(varchar,@age)才行 4.常用的全局变量: @@error:最近一条SQL语句是否用错误,如果用错误,将返回非零值 @@identity:可用来查询最后插入的数据的标识值 5.if (条件) begin 语句 end else ... 注意:if后面有多条语句的时候,要用begin end 6.while(1=1) begin 语句 break end 7.case when 条件1 then 结果1 when 条件2 then 结果2 else 其他结果 end 注意:可加在SQL语句的任何地方 8.批处理可以提高语句的执行效率,批处理结束的标志是'GO' 9.in 或or 策略性能较低,一般为两个SQL语句的效率更高 select * from student where stuNo=2 or stuNo=3 比select * from student where stuNo=2 union select * from student where stuNo=3 的效率低 第四章 1.建立临时表: select * into #temp from stuInfo 临时表保存在临时数据库中 临时表不会从一个会话状态转移到另一个会话状态(只能在创建临时表的查询中查询) 当会话状态结束后临时表会自动清除 与存储过程结合使用 2.子查询 select * from stuInfo where stuAge >(select * from stuInfo where stuName='小李') go 第五章 1.事务:事务及一段SQL代码放到事务中,则这段代码执行时要么失败,要么就成功,失败后,之前执行的代码全部回滚 事务的特性: 原子性:事务的各元素是不可在分的 一致性:事务完成后,数据是一致状态 隔离性:对数据进行修改的所有并发事务是彼此隔离的,一个事务要么在另一个事务之前访问它执行的数据,要么在另一个事务结束后再去访问 持久性:数据的更改是该在硬盘上的 2.事务应用的代码: 例子:张三和李四转账 begin transaction declare @errorSum int set @errorSum = 0 update bank set currentMoney = currentMoney-1000 where customerName='张三' set @erroSum = @errorSum+@@error update bank set currentMoney = currentMoney+1000 where customerName='李四' set @erroSum = @errorSum+@@error if @errorSum > 0 begin print '事务失败,回滚事务' rollback transaction end else begin print '事务成功,提交事务' commit transaction end go 3.索引:缺点:需要更多的硬盘空间,如果插入、更新、删除数据,系统更新索引速度慢 唯一索引:不允许两行具有相同的索引值 主键索引:在创建数据库关系图时,定义为主键列会自动创建主键索引 聚集索引:索引和列值相同,一个表只能有一个,查询速度快 非聚集索引:索引和列值不相同,一个表能有<249个,查询速度慢 创建索引: if exists(select name from sysindexes where name='IX_stuMarks_writtenExam') drop index stuMarks.IX_stuMarks_writtenExam create nonclustered index IX_stuMarks_writtenExam on stuMarks(writtenExam) ---建议不写with fillfactor=30 4.视图:最大的作用在于:查询,能够实现隐藏一些列的信息,更容易理解和获得数据 创建视图: if exists (select * from sysobjects where name ='view_stuInfo_stuMarks') drop view view_stuInfo_stuMarks go create view view_stuInfo_stuMarks as select stuName,stuInfo.stuNo,writtenExam,labExam from stuInfo left join stuMarks on stuInfo.stuNo=stuMarks.stuNo go select * from view_stuInfo_stuMarks //查询视图中的数据 第六章 1.系统存储过程: exec sp_databases --列出当前系统中的数据库 exec sp_renamedb 'Northwind','Northwind1' --更改Northwind数据库名为northwind1 use stuDB go exec sp_tables --当前数据库中可查询对象的列表 exec sp_columns stuInfo --查看表stuInfo中列的信息 exec sp_help stuInfo --查看表stuInfo的所有信息 exec sp_helpconstraint stuInfo --查看表stuInfo的约束 exec sp_helpindex stuMarks --查看stuMarks的索引 exec sp_helptext 'view_stuInfo_stuMarks' --查看视图的语句文本 exec sp_stored_procedures --返回当前数据库中的存储过程列表 2.用DOS命令创建一个文件夹 exec xp_cmdshell 'mkdir D:\book',no_output 3.创建不带参数的存储过程 if exists(select * from sysobjects where name='pro_stu') drop procedure pro_stu go create procedure pro_stu as SQL语句 go 4.创建带输入参数的存储过程 if exists(select * from sysobjects where name='pro_stu') drop procedure pro_stu go create procedure pro_stu @writtenPass int, @labPass int as SQL语句 go 5.创建带输出参数的存储过程 if exists(select * from sysobjects where name='pro_stu') drop procedure pro_stu go create procedure pro_stu @writtenPass int output, @labPass int output as SQL语句 go 6.如何接return 值: if exists(select * from sysobjects where name='pro_stu') drop procedure pro_stu go create procedure pro_stu @notpassSum int output, @writtenPass int=60, @labPass int=60 as print '笔试及格线:'+convert(varchar,@writtenPass)+'机试及格线:'+convert(varchar,labPass) print '参加本次考试没有通过的学员:' select stuName,stuInfo.stuNo,writtenExam,labExam from stuInfo inner join stuMarks on stuInfo.stuNo=stuMarks.stuNo where writtenExam<@writtenPass or labExam<@labPass select @notpassSum=count(stuNo) from stuMarks where writtenExam<@writtenPass or labExam<@labPass return 12 go declare @sum int declare @returnValue int 注意: exec @returnValue = proc_stu @sum output ,64 if @sum>=3 print '未通过人数:'+convert(varchar,@sum)+'人,超过60%,及格分数线还应该下调' else print '未通过人数:'+convert(varchar,@sum)+'人,已控制在60%已下,及格分数线适中' 7.raiserror 可以弥补print不足,即可以在程序中显示输出信息 if exists(select * from sysobjects where name='pro_stu') drop procedure pro_stu go create procedure pro_stu @notpassSum int output, @writtenPass int=60, @labPass int=60 as if(not @writtenPass between 0 and 100) or (not @labPass between 0 and 100) begin raiserror(' 及格线错误,请指定0-100之间,统计中断退出') return end print '笔试及格线:'+convert(varchar,@writtenPass)+'机试及格线:'+convert(varchar,labPass) print '参加本次考试没有通过的学员:' select stuName,stuInfo.stuNo,writtenExam,labExam from stuInfo inner join stuMarks on stuInfo.stuNo=stuMarks.stuNo where writtenExam<@writtenPass or labExam<@labPass select @notpassSum=count(stuNo) from stuMarks where writtenExam<@writtenPass or labExam<@labPass return 12 go declare @sum int declare @return int 注意: exec @return = proc_stu @sum output ,64 if @sum>=3 print '未通过人数:'+convert(varchar,@sum)+'人,超过60%,及格分数线还应该下调' else print '未通过人数:'+convert(varchar,@sum)+'人,已控制在60%已下,及格分数线适中' 8.加密存储过程: alter procedure 存储过程名 with encryption as SQL内容 9.存储过程注意事项: (1)不需要有print[打印出的内容不会到程序中显示] (2)一般和临时表配合使用 (3)执行存储过程就是开启一次会话,执行结束后会话状态结束 (4)和游标配合使用 (5)存储过程没有重载 (6)创建存储过程必须在go的后面,否则报错 (7)存储过程注释: /* 功能 创建日期 修改日期 修改备注 */ 10.游标:可以把存储过程返回的集合中的数据一行一行 --定义游标 declare mycursor cursor for select * from #tempBook --定义参数 declare @first_day int declare @first_pay int declare @second_pay int declare @pay_day int set @total=0 --打开游标 open mycursor --提取第一条数据 fetch next from mycursor into @first_day,@first_pay,@second_pay,@pay_day while @@fetch_status = 0 begin if @pay_day <= @first_day --第一种类型 set @total=@total+@first_pay*@pay_day else --第二种类型 set @total=@total+@second_pay*(@pay_day-@first_day)+@first_day*@first_pay fetch next from mycursor into @first_day,@first_pay,@second_pay,@pay_day end --关闭游标 close mycursor --注销游标 deallocate mycursor GO declare @tatal int exec book_proc 'F0612S288',@tatal output print @tatal 11.触发器:在对表进行插入、更新或删除操作时自动执行的存储过程 (1).它是一种特殊的存储过程 (2).也具备事务的功能 (3).它能在多表之间执行特殊的业务规则 (4).触发器通常用于强制业务规则 (5).触发器是一种高级约束,可以定义比用check约束更为复杂的约束,可执行复杂的SQL语句(if/while/case),可引用其它表中的列 详解:触发器触发时: 系统自动在内存中创建deleted表或inserted表,只读,不允许修改;触发器执行完成后,自动删除 inserted 表 : 临时保存了插入或更新后的记录行,可以从inserted表中检查插入的数据是否满足业务需求,如果不满足,则向用户报告错误消息,并回滚插入操作 deleted 表 临时保存了删除或更新前的记录行,可以从deleted表中检查被删除的数据是否满足业务需求,如果不满足,则向用户报告错误消息,并回滚插入操作 我的理解:当更改一个表的数据的时候,如果为该表创建了触发器,相关的表的数据会自动的更改 注意:触发器定义在特定的表上,与表相关 自动触发执行 不能直接调用 是一个事务(可回滚) 例子1:insert触发器,在transInfo表上创建触发器,当对transInfo表执行insert语句时自动触发trig_transInfo触发器 create trigger trig_transInfo on transInfo for[after] insert as declare @type char(4),@outMoney MONEY declare @myCardID char(10),@balance MONEY select @type=transType,@outMoney=transMoney,@myCardID=cardID from inserted if (@type='支取') update bank set currentMoney=currentMoney-@outMoney where cardID=@myCardID else update bank set currentMoney=currentMoney+@outMoney where cardID=@myCardID go 例子2:delete触发器 create trigger trig_delete_transInfo on transInfo for delete as print '开始备份数据,请稍后......' if not exists(select * from sysobjects where name='backupTable') select * into backupTable from deleted else begin insert into backupTable select * from deleted print '备份数据成功,备份表中的数据为:' select * from backupTable end go 例子3:update触发器 create trigger trig_update_bank on bank for update as declare @beforeMoney money,@afterMoney money select @beforeMoney=currentMoney from deleted select @afterMoney=currentMoney from inserted if ABS(@afterMoney-@beforeMoney)>20000 begin print '交易金额:'+convert(varchar(8), ABS(@afterMoney-@beforeMoney)) raiserror('每笔交易不能超过2万元,交易失败',16,1) rollback tansaction end go 例子4: 问题:交易日期一般由系统自动产生,默认为当前日期。为了安全起见,一般禁止修改,以防舞弊。 update(列名)函数可以检测是否修改了某列 create trigger trig_update_transInfo on transInfo for update as if update(transDate) begin print '交易失败.....' raiserror(‘安全警告:交易日期不能修改,由系统自动产生',16,1) rollback transaction end go 课外补充: 1.select * from table_name1 where exists(select * from table_name2 where 条件) 2.image 变长二进制数据,最大长度为2^31-1(2G) 可存图片,电影,等等 3.alter table userInfo add constraint CK_PID check(len(PID)=18 or len(PID)=15), constraint CK_telephone check(telephone like replicate('[0-9]',4)+'-'+replicate('[0-9]',8) or telephone like replicate('[0-9]',3)+'-'+replicate('[0-9]',8) or len(telephone)=11) 4. 联合查询 union运算可以把多个查询的结果合并到一个结果集里显示. union运算的一般语法:[表]查询1 union [ALL]查询2 UNION … 例:返回巴西所有供给商和客户的名字和城市 select companyName,city from suppliers where country = 'Brazil' union select companyName,city from customers where country = 'Brazil' 注意: 缺省的情况下,union子句不返回重复的记录,如果想显示所有记录,可以加ALL选项 union运算要求查询具有(相同数目的字段),但字段数据类型不必相同. 每一个查询参数中可以使用GROUP BY子句或HAVING子句进行分组.要想以指定的顺序来显示返回的数据,可以在最后一个查询的尾部使用OREER BY子句. 5.新建默认值 alter table [表名] add constraint 默认值名 default '51WINDOWS.NET' for [字段名] 删除默认值 alter table [表名] drop constraint 默认值名 6. 删除Sql Server 中的日志,减小数据库文件大小 dump transaction 数据库名 with no_log backup log 数据库名 with no_log dbcc shrinkdatabase(数据库名) exec sp_dboption ’数据库名’, ’autoshrink’, ’true’ 示例: dump transaction MyDocument with no_log backup log MyDocument with no_log dbcc shrinkdatabase(MyDocument) exec sp_dboption 'MyDocument','autoshrink','true' 7.返回所有有下过采购单的供应商信息,同时还需要返回供应商最后一次下采购单的时间 select Provider.*,md from Provider inner join ( select max(SDate) md,ProID from Stock group by ProID ) tempdt on tempdt.ProID=Provider.ProID 8.显示今天生日的元老,即生日与今天月日相同 select * from bbsusers where month(ubirthday)=month(getdate()) and day(ubirthday)=day(getdate())
9.select * from table with (nolock) http://www.cnblogs.com/xiaofei59/archive/2011/04/15/2017359.html
要提升SQL的查询效能,一般来说大家会以建立索引(index)为第一考虑。其实除了index的建立之外,当我们在下SQL Command时,在语法中加一段WITH (NOLOCK)可以改善在线大量查询的环境中数据集被LOCK的现象藉此改善查询的效能。
不过有一点千万要注意的就是,WITH (NOLOCK)的SQL SELECT有可能会造成Dirty Read