SELECT * FROM `employees` WHERE `last_name` LIKE '%a%'; # 包含a,不区分大小写
SELECT * FROM `employees` WHERE `last_name` LIKE '%e'; # 最后一个字符为e
SELECT * FROM `employees` WHERE `last_name` LIKE 'e%'; # 最后一个字符为e
SELECT * FROM `employees` WHERE `last_name` LIKE '__x%'; # 第三个字符为x
SELECT * FROM `employees` WHERE `last_name` LIKE '_\_%'; # 第二个字符是下划线的
SELECT * FROM `employees` WHERE `last_name` LIKE '_$_%' ESCAPE '$'; # 第二个字符是下划线的
小技巧: ESCAPE 是指定某字符为转义字符的命令
in 语句
用于查询某字段的值是否属于指定的列表之内
a in(value1, value2, value3)
a not in(value1, value2, value3)
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
SELECT last_name, department_id FROM employees WHERE department_id in (30, 50, 90);
SELECT last_name, department_id FROM employees WHERE department_id = 30 OR department_id = 50 OR department_id = 90;
SELECT * FROM employees WHERE job_id NOT IN ('SH_CLERK', 'IT_PROG')
SELECT * FROM employees WHERE NOT(job_id = 'SH_CLERK' OR job_id = 'IT_PROG');
在SQL中数值类的值直接写,非数值类的值用单引号引起来
between and 语句
判断某个字段的值是否在某个区间
between and / not between and都可以
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
SELECT department_id, last_name FROM employees WHERE department_id BETWEEN 30 AND 90;
SELECT department_id, last_name FROM employees WHERE department_id >= 30 AND department_id <= 90;
SELECT last_name, salary, salary * 12 * (1 + IFNULL(commission_pct, 0)) AS Annual FROM employees WHERE salary * 12 * (1 + IFNULL(commission_pct, 0)) NOT BETWEEN 100000 AND 200000;
SELECT last_name, salary, salary * 12 * (1 + IFNULL(commission_pct, 0)) AS Annual FROM employees WHERE salary * 12 * (1 + IFNULL(commission_pct, 0)) < 100000 OR salary * 12 * (1 + IFNULL(commission_pct, 0)) > 200000;
SELECT * FROM employees WHERE commission_pct IS NULL;
SELECT * FROM employees WHERE commission_pct IS NOT NULL;
SELECT * FROM employees WHERE commission_pct = NULL; # 这种写法是错误的,因为=只能判断数值
SELECT * FROM employees WHERE salary = 10000;
SELECT * FROM employees WHERE salary IS 10000; # 这种写法是错误的,因为IS 只能判断NULL
# 安全等于 <=> 既可以判断具体数值,也可以判断NULL
SELECT * FROM employees WHERE salary <=> 10000;
SELECT * FROM employees WHERE commission_pct <=> NULL;
排序查询
select 查询列表 from 表名 (where 筛选条件) order by 排序列表
执行顺序:
from
where
select
order by
排序列表可以是字段,多个字段,表达式,函数,列数以及以上的组合
升序 (asc) (默认)
降序desc
按字段案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
SELECT * FROM employees WHERE employee_id > 120 ORDER BY salary ASC;
SELECT * FROM employees WHERE employee_id > 120 ORDER BY salary DESC;
SELECT * FROM employees WHERE employee_id > 120 ORDER BY salary;
按表达式和函数案例
1 2 3 4
SELECT *, salary * 12 * (1 + IFNULL(commission_pct,0)) AS Annual FROM employees WHERE commission_pct IS NOT NULL ORDER BY salary * 12 * (1 + IFNULL(commission_pct, 0)) DESC;
如果你认为order by后面太长了,可以按别名排序
按别名排序
where 不能按别名筛选的原因是执行顺序在select语句之前
案例
1 2 3 4
SELECT *, salary * 12 * (1 + IFNULL(commission_pct,0)) AS Annual FROM employees WHERE commission_pct IS NOT NULL ORDER BY Annual DESC;
按字节(字符串)长度排序 (LENGTH 函数)
案例
1 2 3 4 5 6
SELECT LENGTH(last_name), last_name FROM employees;
SELECT last_name FROM employees ORDER BY LENGTH(last_name);
组合排序
案例 (注意ORDER BY 语句后成分的顺序)
1 2 3
SELECT last_name, salary, department_id FROM employees ORDER BY salary ASC, department_id DESC;
按某一列(列数排序)(不常用)
案例:按第二列排序
1 2 3 4 5 6 7
SELECT * FROM employees ORDER BY first_name; # 字母会自动按abcd顺序排序
SELECT * FROM employees ORDER BY 2; # 字母会自动按abcd顺序排序
常见函数 (单行函数:输入一个参数,返回一个结果) 所有函数后最好紧贴括号
CONCAT 拼接字符
1 2
SELECT CONCAT('hello ', last_name) FROM employees;
SELECT COUNT(1), department_id FROM employees GROUP BY department_id HAVING COUNT(1) > 5;
# 每个工种有奖金的员工的最高工资大于12000的工种编号和最高工资
SELECT job_id, MAX(salary) AS 'zui_gao_gong_zi' FROM employees WHERE commission_pct > 0 GROUP BY job_id HAVING MAX(salary) > 12000;
# 领导编号大于102的每个领导手下的最低工资大于5000的领导编号和最低工资
SELECT manager_id, MIN(salary) FROM employees WHERE manager_id > 102 GROUP BY manager_id HAVING MIN(salary) > 5000;
1 2 3 4 5 6
SELECT MAX(salary), job_id FROM employees WHERE commission_pct IS NULL GROUP BY job_id HAVING MAX(salary) > 6000 ORDER BY MAX(salary) ASC;
按多个字段分组
1 2 3 4
SELECT job_id, department_id, MIN(salary) FROM employees GROUP BY job_id, department_id ORDER BY MIN(salary) DESC;
基础查询总结
1 2 3 4 5 6
SELECT FROM WHERE GROUP BY HAVING ORDER BY
顺序:
from
where
group
having
select
order by
连接查询
等值连接
1 2 3
SELECT 查询列表 FROM 表名1, 表名2 WHERE 等值连接的连接条件
特点:为了解决表中字段重名的问题,往往为表起别名,提高语义性
表的顺序无要求
连接后一定把反引号加好
查询员工名和部门名
起完别名后 select一定用别名. 因为执行顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SELECT e.last_name, d.`department_name` FROM employees AS `e`, departments AS `d` WHERE e.`department_id` = d.`department_id`;
SELECT `department_name`, `city` FROM departments d, locations l WHERE d.`location_id` = l.`location_id` AND d.`department_id` > 100;
SELECT `last_name`, `department_name` FROM departments d, employees e WHERE d.`department_id` = e.`department_id` AND e.`commission_pct` IS NOT NULL;
SELECT department_name, city FROM departments d, locations l WHERE d.`location_id` = l.`location_id` AND city LIKE '_o%';
再加上分组 连接后一定把反引号加好
1 2 3 4 5 6 7 8 9 10
SELECT COUNT(1), l.city FROM departments d, locations l WHERE d.`location_id` = l.`location_id` GROUP BY city;
SELECT e.`manager_id`, d.`department_name`, MIN(e.`salary`)# MIN(salary) FROM employees e, departments d WHERE e.`commission_pct` IS NOT NULL AND e.`department_id` = d.`department_id` GROUP BY e.`department_id`, e.`manager_id`; ORDER BY MIN(e.`salary`) DESC;
SELECT e.`last_name`, d.`department_name` FROM employees e LEFT JOIN departments d ON e.`department_id` = d.`department_id`;
/*等效于*/
SELECT e.`last_name`, d.`department_name` FROM employees e JOIN departments d ON e.`department_id` = d.`department_id`;
SELECT e.`last_name`, d.`department_name` FROM employees e LEFT JOIN departments d ON e.`department_id` = d.`department_id` WHERE d.`department_id` IS NULL;
SELECT e.`last_name`, d.`department_name` FROM departments d RIGHT JOIN employees e ON e.`department_id` = d.`department_id` WHERE d.`department_id` IS NULL;
案例:显示哪个部门没有员工
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# 这是我自己想的用嵌套查询的解决方案 SELECT v.`num`, d.`department_name` FROM departments d LEFT JOIN( SELECT COUNT(1) AS `num`, department_id FROM employees GROUP BY department_id ) v ON v.`department_id` = d.`department_id`;
# 教程的方法 SELECT d.*, e.* FROM departments d LEFT JOIN employees e ON d.`department_id` = e.`department_id`;
SELECT d.`department_id` FROM departments d LEFT JOIN employees e ON d.`department_id` = e.`department_id` WHERE e.`employee_id` IS NULL;
子查询 嵌套查询
主查询 = 外查询, 子查询 = 内查询
需要表的地方用()括起来一个SELECT查询
不一定只有SELECT语句才会用嵌套查询,INCERT, CREATE 等命令中也会出现
嵌套查询可以出现在:
SELECT后面, 要求:子查询的结果为单行单列(标量子查询)
FROM后面,要求:子查询的结果可以为多行多列
WHERE后面,要求:子查询结果必须为单列(单行子查询,多行子查询)
EXIST后面,要求子查询结果必须为单列(相关子查询)
特点:
子查询放在条件中必须放在条件的右侧
1 2 3
department_id > (SELECT...) # 正确
(SELECT ...) < department_id # 错误
子查询一般放在小括号中
子查询的执行有限执行括号内的
单行子查询对应使用单行操作符(关系运算符): > < >= <= = <>
多行子查询对应了 多行操作符: any / in / some / all
单行子查询
案例:查询和员工zoltkey相同部门的员工姓名和工资
1 2 3 4 5 6 7 8 9 10 11
SELECT department_id FROM employees WHERE last_name = 'Zlotkey';
SELECT last_name, salary FROM employees WHERE department_id = ( SELECT department_id FROM employees WHERE last_name = 'Zlotkey' );
案例:查询工资比平均工资高的员工号,姓名和工资
1 2 3 4 5 6
SELECT employee_id, last_name, salary FROM employees WHERE salary > ( SELECT AVG(salary) FROM employees );
案例: 删选最低工资比部门id=50的最低工资高的各部门的最低工资
1 2 3 4 5 6 7 8
SELECT MIN(salary), department_id FROM employees GROUP BY department_id HAVING MIN(salary) > ( SELECT MIN(salary) FROM employees WHERE department_id = 50 );
WHEN 布尔表达式1 then 结果表达式1 # 布尔(boolean)表达式指返回值为ture或false的表达式
WHEN boolen2 then result2
...
WHEN boolenn then resultn
[ELSE resultn+1]
END
1 2 3 4 5 6 7
SELECT a.GoodsID, 商品销售类别 = CASE WHEN COUNT(b.GoodsID)>10 THEN '热门商品' WHEN COUNT(b.GoodsID)BETWEEN 1 AND 10 THEN '普通商品' ELSE '滞销商品' END FROM Table_Goods a LEFT JOIN Table_Sales b ON a.GoodsID=b.GoodsID GROUP BY a.GoodsID
INTO 将查询结果保存在新表中
表前面加一个#号代表局部临时表 (当前查询1次有效)
表前面加两个#号代表全局临时表
只有表名为永久表
1 2 3
SELECT * INTO #HD_Customer FROM Table_CUstomer WHERE ...
所以GROUP BY 和ORDER By之类的写在最后一个SELECT后面但要用第一个SELECT中的列名
INTERSECT 交运算 返回同时在两个集合中出现的记录
1 2 3 4 5 6 7 8 9
SELECT order1
INTERSECT
SELECT order2
INTERSECT ...
SELECT ordern
EXCEPT 差运算 返回第一个查询中有第二个查询中没有的记录
1 2 3 4 5 6 7 8 9
SELECT order1
EXCEPT
SELECT order2
EXCEPT ...
SELECT ordern
子查询 subquery
参考前面
1 2 3 4 5
WHERE expression [NOT] IN (subquery)
WHERE expression compression_operator [ANY|ALL]
WHERE [NOT] EXISTS (subquery) # 存在性查询
插入
1
INTERT 表名 Vales (值1, 值2) # 值的顺序必须和表里的一样
更新
1 2
UPDATE 表名 Set 字段 = 值 WHERE ... # 不带where整个表都改了, where中要带主键
删除
1 2
DELETE 表名 WHERE ...
开窗函数 OVER
指把count, sum, avg等聚合计算赋值到每一行后面而不是单单给出结果
1 2 3 4 5 6
SELECT Cno, CName, Semester, Credit, SUM(Credit) OVER(PARTITION BY Semester) AS 'Total', AVG(Credit) OVER(PARTITION BY Semester) AS 'Avg', MIN(Credit) OVER(PARTITION BY Semester) AS 'Min', MAX(Credit) OVER(PARTITION BY Semester) AS 'Max' FROM Course
排名函数 RANK()
1 2 3 4 5
SELECT OrderID, ProductID, OrderQty, RANK() OVER (PARTITION BY OrderID ORDER BY OrderQty DESC) AS RANK FROM Order Detail GROUP BY OrderID
DENSE_RANK()函数也用于排序,与RANK()的区别是前者没有并列,后者有并列
公用表表达式 (生成临时表) WITH
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# 定义:
WITH BuyCount(CardID, Count) AS( SELECT CardID, COUNT(*) FROM Table_SaleBill GROUP BY CardID )
# 使用
AS( SELECT CardID, Counts FROM BuyCount ORDER BY Counts )
案例 (以下操作均再SQL server 2008 express 环境基础上使用SSMS 2008 express 操作完成)
alter database StudentDB MODIFY file( name = StudentDB, /*创建时主数据文件和数据库文件的名字一样,这里不要搞混了*/ size = 5mb )
添加文件组
1 2 3 4 5 6 7 8 9 10 11 12
/*添加文件组,添加一个辅助数据文件到新的文件组*/ alter database StudentDB add filegroup GData go alter database StudentDB add file( name = 'StuDB3', filename = 'D:\DATABASE\DATA2\StuDB3.ndf' ) to filegroup GData
/*go: 批处理:同时执行上下两个命令. 注意go的那行不能加注释。。啥毛病都是,吐了*/
删除数据库辅助文件
1 2 3
--删除数据库的辅助数据文件StuDB3 alter database StudentDB remove file StuDB3
create table Tb_StudentInfo( StdInfoID int identity(1, 1) primary key not null, /*identity(m, n)从m开始以n为步长自动增长*/ StdName varchar(20) not null, StdYear int not null ) on YearOrderPartScheme(StdYear) /*根据stdyear使用YearOrderPartScheme分区方案来进行分区*/
-- 查看所在分区
select *, $partition.YearOrderPartFunc(StdYear) as '所属分区' from Tb_StudentInfo
create view view_teachercourse( 课程名称, 教师姓名 ) as select courseinfoname, teacherinfoname from dbo.courseinfo as a join dbo.teachercourse as b join dbo.teacherinfo as c on b.teachercourseID = c.teachInfoID on a.CourseInfoID = b.CourseInfoID
-- 查看视图
select * from dbo.view_teachercourse
-- 查看视图的定义
sp_helptext view_teachercourse
-- 修改视图
alter view view_teachercourse( 课程名称, 教师姓名, 老师学历 ) as select courseinfoname, teacherinfoname, teacherknowl from dbo.courseinfo as a join dbo.teachercourse as b join dbo.teacherinfo as c on b.teachercourseID = c.teachInfoID on a.CourseInfoID = b.CourseInfoID
create table StudentDB.my_schema.temp_table( stu_id int identity(1,1) primary key not null, /*不能为int指定列宽*/ stu_name varchar(20) not null, stu_age int )
drop table StudentDB.my_schema.temp_table
-- 缺省约束 default constrain (定义默认值)
--- (1)创建表的时候 (其他的约束也都可以在这两种时刻进行)
create table StudentDB.my_schema.temp_table( classID int not null, classdepart varchar(20) not null default('软件学院'), studentnumber int not null default(0) /*注意缺省值设定应与列数据类型一致*/ )
--- (2)修改表的时候
alter table StudentDB.my_schema.temp_table add constraint df_classID default(1001) for classID
drop table StudentDB.my_schema.temp_table
-- 唯一约束 unique constrain (字段值取值唯一但允许null)
create table StudentDB.my_schema.temp_table( stdID int not null, stdInfoNum varchar(20) not null unique, stdIDcardnum varchar(18) )
alter table StudentDB.my_schema.temp_table add constraint ix_stdIDcardnum unique(stdIDcardnum)
drop table StudentDB.my_schema.temp_table
-- 检查约束 check constrain (限制范围)
create table StudentDB.my_schema.temp_table( stuID int not null, courseID int not null, grade numeric check(grade >= 0 and grade <= 100), grade2 numeric )
alter table StudentDB.my_schema.temp_table add constraint ck_grade2 check(grade2 between 0 and 100) /*另一种约定上下限的方式*/
drop table StudentDB.my_schema.temp_table
-- 主键约束 primary key constrain
create table StudentDB.my_schema.temp_table( stuID int not null primary key, courseID int not null, grade numeric check(grade >= 0 and grade <= 100), grade2 numeric )
alter table StudentDB.my_schema.temp_table add constraint pk_courseID primary key(courseID)
/*创建复合主键的表:*/
create table studentCourse( stdID int not null, courseID int not null, score numeric not null, constraint pk_stdid_courseid primary key(stdID, courseID) )
drop table studentCourse
drop table StudentDB.my_schema.temp_table
-- 外键约束 foreign key constrain
create table StudentDB.my_schema.temp_table( stuID int not null primary key, courseID varchar(20) not null foreign key references my_schema.Tb_Stu_Info(Stu_No), /*注意外键的数据类型要与其引用的*/ courseID2 varchar(20) not null )
alter table StudentDB.my_schema.temp_table add constraint fk_courseID2 foreign key(courseID2) references my_schema.Tb_Stu_Info(Stu_No)
-- 删除约束 alter table StudentDB.my_schema.temp_table drop constraint FK__temp_tabl__cours__286302EC /*从对象资源管理器里拖拽进来的外键约束*/
索引
1 2 3 4 5 6 7 8 9 10 11 12 13
/*索引*/
-- 创建索引 create clustered index pk_courseID /*聚集索引(创建之前确保没有其他的聚集索引如主键之类的)(散列是CREATE INDEX xxx using hash on table(column))*/ on StudentDB.my_schema.temp_table(courseID desc) /*降序*/
-- 重新生成索引 alter index pk_courseID on StudentDB.my_schema.temp_table rebuild
-- 删除索引 drop index pk_courseID on StudentDB.my_schema.temp_table
/*排序 group by*/ -- 排序默认升序asc;降序是desc select stdinfonum, stdinfoname,stdinfobirth from dbo.studentinfo where stdinfobirth >= '1990-1-1' order by stdinfobirth desc
/*查询包含字符串*/ select * from dbo.studentinfo where stdinfoname like '张%' /*张+任意字符*/
/*between and*/ select * from dbo.studentinfo where stdinfoyear between 2007 and 2009 -- 等效于 select * from dbo.studentinfo where stdinfoyear >= 2007 and stdinfoyear <=2009 -- 等效于 select * from dbo.studentinfo
/*in*/ select * from dbo.studentinfo where stdinfoyear not in (2007, 2008, 2009)
/*is null*/
/*把聚合函数的结果汇总在每一行*/
select stdinfoname, stdinfosex, stdinfonatns from dbo.studentinfo compute count(stdinfoname)
select stdinfoname, stdinfosex, stdinfonatns from dbo.studentinfo order by stdinfonatns compute count(stdinfonatns) by stdinfonatns
判断if语句
案例:判断学生(ID = 6)是否已经选了3门以上的课程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
declare @sname varchar(50), @num int
select @sname = StdInfoName /*赋值的一种方法*/ from dbo.StudentInfo where stdInfoID = 6
set @num = (select COUNT(*) from dbo.StudentCourse group by StdInfoID having StdInfoID = 6) /*赋值的另一种方法*/
if @num >= 3 begin print @sname + ',你已经完成了选课!' end else print @sname + ',你还要继续选课' /*只有一个命令的时候begin end 可写可不写*/
判断case语句
案例:把性别中的‘男’显示为male,女生同样
1 2 3 4 5
select SrdInfoName, 性别 = CASE WHEN StdInfo Sex = '男' then 'male' WHEN StdInfoSex = '女' then 'female' End FROM dbo.StudentInfo
循环结构
案例计算1 - 100 以内能被3整除的最大数字
1 2 3 4 5 6 7 8 9 10 11 12
decalre @x int = 100
while(@x >= 1) begin if(@x % 3 = 0) break set @x- = 1 end
print 'the largest number between 1 and 100 which can be devide by 3 is'
/*定义存储过程*/ create procedure p_showteachercourse /*procedure 可以简写为 proc*/ AS SELECT TeachInfoName, TeachInfoSex, TeachInfoKnowl, TeachInfoTitle, CourseInfoName From dbo.TeachInfo a join dbo.TeachCourse b on a.TeachInfoID = b.TeachInfoID join dbo.CourseInfo c on b.CourseInfoID = c.CourseInfoID
/*修改存储过程*/ alter procedure p_showteachercourse AS SELECT TeachInfoName, TeachInfoSex, TeachInfoKnowl, TeachInfoTitle, CourseInfoName From dbo.TeachInfo a join dbo.TeachCourse b on a.TeachInfoID = b.TeachInfoID join dbo.CourseInfo c on b.CourseInfoID = c.CourseInfoID where TeachInfoTitle = '副教授'
/*删除存储过程*/ drop procedure p_showteachercourse drop proc p_showteachercourse
/*带参数的存储过程*/ create proc p_showteachercourse @teachername varchar(30) as SELECT TeachInfoName, TeachInfoSex, TeachInfoKnowl, TeachInfoTitle, CourseInfoName From dbo.TeachInfo a join dbo.TeachCourse b on a.TeachInfoID = b.TeachInfoID join dbo.CourseInfo c on b.CourseInfoID = c.CourseInfoID where TeachInfoName = @teachername
-- 执行(执行时需要输入参数) dbo.p_showteachercourse '李静'
/*带输出的存储过程*/ create proc AddTeaCourse @TeaInfoID int, @CourseInfoID int, TeaCourseID int output /*输出*/ as insert dbo.TeachCourse values(@TeaInfoID, @TeaCourseID) --设置输出参数,用来储存自动增长的编号 set @TeacourseID = scope_identity()
create trigger trig_insertTeachinfo on dbo.TeachInfo after insert /*后触发器*/ as begin transaction /*事务的开始*/ if exists ( select * from insertted a where a.DepInfoID not in( select DepInfoID from dbo.DepInfo ) begin /*if的判断体*/ raiserror('数据一致性验证!', 16, 1) /*报错消息:如果出错,会报:数据一致性验证! 级别16, 状态1*/ rollback transaction /*回滚事务*/ end else commit transaction /*提交事务*/ ) /*inserted 是一个逻辑表,存放插入之后记录*/
-- 更新分为两个步骤:删除和插入 -- 牵扯到两个逻辑表:deleted(被删除的记录),inserted(存放插入之后记录) create trigger trig_update class on dbo.ClassInfo after update as if update(ClassInfoID) /*如果更新的是classinfoid的话更新其他classname啥的则不会触发*/ begin update dbo.StudentInfo set ClassInfoID = ( select ClassInfoID from inserted where classinfoid = ( select classinfoid from deleted ) ) end
-- 测试 update dbo.classinfo set classinfoid = 444 where classinfoid = 4
案例delete后触发器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
create trigger trig_deleteStudent on dbo.StudentInfo after delete as begin declare @stdinfoID int select @stdInfoID = deleted.stdInfoID from deleted
delete dbo.StudentXourse where StdInfoID = @stdInfoID end
-- 测试 delete dbo.StudentInfo where StdInfoID = 2
案例(前触发器)不允许删除已经存在的记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
create trigger trig_deleteDep on dbo.DepInfo instead of delete as begin declare @delCount int select @delcount = count(*) from deleted if @delCuunt > 0 begin raiserror ('不能删除院系表中的任何记录!', 10, 1) -- rollback transaction /*推荐回滚一下,不回滚也可以*/ end end
-- 测试 delete dbo.DepInfo
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*删除触发器*/ drop trigger trig_deleteDep
/*修改触发器*/ alter trigger trig_deleteDep /*后面和create的一样*/ on dbo.DepInfo instead of delete as begin declare @delCount int select @delcount = count(*) from deleted if @delCuunt > 0 begin raiserror ('不能删除院系表中的任何记录!', 10, 1) -- rollback transaction /*推荐回滚一下,不回滚也可以*/ end end
create trigger trig_stdinfoclassnum on dbo.StudentInfo after insert, delete as if(exists (select * from inserted)) begin update dbo.classinfo set classinfosum + = 1 where classinfoid = (selected classinfoid from inserted) end
if(exists (select * from deleted)) begin update dbo.classinfo set classinfosum - = 1 where classinfoid = (selected classinfoid from deleted) end
create function FTitleSum(@depName varchar(20)) returns int /*返回老师总人数*/ as begin declare @num int select @num = count(*) from dbo.Teachinfo where DeptInfoID = ( select DeptInfoID from dbo.DepInfo where DeptInfoName = @depName ) return @num end
/*表值函数*/ create function FSelTeach(@depName varchar(20)) returns table as return (select TeacName from dbo.Teachinfo where DeptInfoID = ( select DeptInfoID from dbo.DepInfo where DeptInfoName = @depName ))
--调用 declar @name varchar(20) = '信息工程系' select * from FSelTeach(@name)
/*多语句表值函数*/
select CourseInfoName, CourseInfoRestPer from dbo.CourseInfo c join dbo.TeachInfo a join dbo.TeachCourse b on a.TeachInfoID = b.TeachInfoID on c.CourseInfoID = b.CourseInfoID where TeachInfoName = @teachername
create function FSelCourse(@teachName varchar(20)) returns @teach_Course table( 课程名称 varchar(80), 理论学时 int, ) /*定义返回的表的结构*/ as begin insert @teach_Course select CourseInfoName, CourseInfoRestPer from dbo.CourseInfo c join dbo.TeachInfo a join dbo.TeachCourse b on a.TeachInfoID = b.TeachInfoID on c.CourseInfoID = b.CourseInfoID where TeachInfoName = @teachername return @teach_Course end
-- 调用 declare @tname varchar(20) set @tname = '王钢蛋' select * from FSelCourse(@tname)
/*声明游标*/ declare student_cursor cursor for select StdInfoName, StdInfoSex, StdInfoNatns from dbo.StudentInfo where StdInfoNatns = '汉' and StdInfoSex = '男'
/*打开游标*/ open student_cursor
/*提取数据*/ fetch next from student_cursor into @sname, @ssex, @snatns /*展示数据*/ while @@FETCH_STATUS = 0 begin print '学生姓名:' + @sname + '性别' + @ssex + '民族' + @snatns fetch next from student_cursor into @sname, @ssex, @snatns end
/*关闭游标*/ close student_cursor
/*释放游标*/ deallocate student_cursor
安全管理(权限)
创建登录名
1 2 3
create login [pcname\username] from windows with default_database= [master]
1 2 3 4 5 6
create login test_user with password = '123456', default_database= [master], /*默认设置成master,否则会报错 with 有一个就可以,后面不用加with*/ check_expiration = on, /*强制密码策略*/ check_policy = on
修改密码
1 2 3
alter login test_user with password = '6666' old_password = '123456`'
禁用登陆
1
alter login test_user disable /*启用时enable*/
删除登录名
1
drop login test_user
创建数据库用户并绑定到服务器登录名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
create login teachUser with password = '123456' default_database = [master] go use StudentDB go create user teach1 for login teachUser /*一个数据库用户只能的关联到一个服务器登录名*/
-- 更换数据库用户 alter user teach1 with name = teach2
-- 删除数据库用户 drop user teach2 /*拥有架构的用户无法删除*/
数据库用户权限管理
1 2 3 4 5 6 7 8
/*授权*/ grant select on TeachInfo to teach1 /*授权要给user而不是login*/