【SQL Server】再一次数据库练习——题目+思路+答案

第一次练习【SQL Server】一次数据库练习——题目+思路+答案

第二次练习【SQL Server】又次数据库练习——题目+思路+答案
 
 

use NetMusicShop
go


---- PPT7 —— 触发器 ----

-- 为Users表创建一个触发器,不允许插入名为admin或"管理员"的用户,也不允许将用户名修改为admin或"管理员"
-- Requirements :
-- 1. 分别用 after(for) 和 instead of 两种触发器来实现,并比较它们的不同
-- 2. 给出测试代码验证该触发器


-- after(for)触发器

-- 基本思路:
-- 1. 先通过deleted表中是否有记录,来判断触发触发器的是insert还是update:
--			如果deleted表有记录,则进行了更新(update)操作;如果deleted表为空,则进行了插入(insert)操作
-- 2. 核心思路是【对Users表进行相反的操作】:
--			如果是更新,就更新回去;如果是插入,就对Users表进行一次删除
create trigger tri_lolisuki on Users
after insert, update
as
begin
	declare @deleled_name nvarchar(20);
	select @deleled_name = (select userName from deleted);
	if(@deleled_name is not null)		-- 如果deleted表非空,则一定是进行了更新操作
	begin
		update Users
		set UserName = @deleled_name where UserName = 'admin' or UserName = '管理员';
	end
	else			-- 否则进行的是插入操作
	begin
		delete from Users 
		where UserName = 'admin' or UserName = '管理员';
	end
end


-- instead of 触发器

-- 基本思路:
-- 1. 同样根据deleted表是否为空,对insert和update进行区分
-- 2. 核心思路是【根据inserted表预先进行判断,是否需要手动进行insert或update的操作】
-- 3. 因为instead of 触发器拦截了所有的insert和update操作(即使与UserName无关!)
--	  这些操作都需要我们手动完成,逐条把inserted表的记录移到Users表中,极其麻烦
--    所以在设计表时,一个表不要有太多的属性列
create trigger tri_lolisaikou on Users
instead of insert, update
as
begin
	declare @deleted_name varchar(20);
	select @deleted_name = (select UserName from deleted);

	declare @UserName varchar(20);				select @UserName = (select UserName from inserted);
	declare @UserPassword varchar(6);			select @UserPassword = (select UserPassword from inserted);
	declare @UserSex char(2);					select @UserSex = (select UserSex from inserted);
	declare @UserRealName varchar(20);			select @UserRealName = (select UserRealName from inserted);
	declare @UserAgeRange char(8);				select @UserAgeRange = (select UserAgeRange from inserted);
	declare @UserAddress varchar(256);			select @UserAddress = (select UserAddress from inserted);
	declare @UserPostCode CHAR(6);				select @UserPostCode = (select UserPostCode from inserted);
	declare @UserPhone varchar(32);				select @UserPhone = (select UserPhone from inserted);
	declare @UserEmail varchar(50);				select @UserEmail = (select UserEmail from inserted);
	declare @UserRegisterTime smalldatetime;	select @UserRegisterTime = (select UserRegisterTime from inserted);
	declare @UserAdvancePayment numeric(8, 2);	select @UserAdvancePayment = (select UserAdvancePayment from inserted);

	if(@inserted_name in ('admin', '管理员'))	-- 如果更新或插入的UserName不合规,则不再进行手动update或insert操作
		select '无法更新和删除';
	else
	begin
		if(@deleted_name is not null)			-- 分情况,进行手动update和insert
		begin
			update Users
			set UserName = @UserName, UserPassword = @UserPassword, UserSex = @UserSex, UserRealName = @UserRealName,
			    UserAgeRange = @UserAgeRange, UserAddress = @UserAddress, UserPostCode = @UserPostCode,UserPhone = @UserPhone,
			    UserEmail = @UserEmail, UserRegisterTime = @UserRegisterTime, UserAdvancePayment = @UserAdvancePayment
			where UserName = @deleted_name;
		end
		else
		begin
			insert Users(UserName,UserPassword,UserSex,UserRealName,UserAgeRange,
                    UserAddress,UserPostCode,UserPhone,UserEmail, UserRegisterTime, UserAdvancePayment)
			values(@UserName, @UserPassword, @UserSex, @UserRealName, @UserAgeRange,
                    @UserAddress, @UserPostCode, @UserPhone, @UserEmail, @UserRegisterTime, @UserAdvancePayment)
		end
	end
end



-- test

drop trigger tri_lolisuki
drop trigger tri_lolisaikou

select * from Users	 -- 查看效果 

insert into Users(UserName,UserPassword,UserSex,UserRealName,UserAgeRange,UserAddress,UserPostCode,UserPhone,UserEmail)
values('管理员','123456','男','loli','12~13岁','山东省临沂市','100000','13331022500','[email protected]')
-- 尝试插入UserName为'管理员'的一条记录,插入失败(符合预期)

insert into Users(UserName,UserPassword,UserSex,UserRealName,UserAgeRange,UserAddress,UserPostCode,UserPhone,UserEmail)
values('lolikon','123456','男','loli','12~13岁','山东省临沂市','100000','13331022500','[email protected]')
-- 尝试插入UserName为'lolikon'的一条记录,插入成功(符合预期)

update Users
set UserName = '管理员' where UserName = 'wz'
-- 尝试修改某条记录的UserName为'管理员',更新失败(符合预期)

update Users
set UserName = 'lolikon' where UserName = 'wz'
-- 尝试修改某条记录的UserName为'lolikon',更新成功(符合预期)


-- after(for)触发器 和 instead of 触发器 的异同:
-- 1. 不管是"之后"还是"之前"哪一种触发器,deleted表和inserted表都已经有记录了
-- 2. 但它们的使用场景差别很大:
--	  after触发器已经完成了所有的操作,它发挥作用的关键通常在于deleted表和inseted表的记录
--    instead of 触发器会拦截操作,只是一个引火索,真正执行的代码是触发器中的代码(一次它内部的语句通常分支众多且代码量大)








---- PPT8 —— T-SQL ----

-- 1.查询订单表Orders,将所有的订单状态列OrderIsConfirm, OrderIsPayment, OrderIsConsignment, OrderIsPigeonhole
--	 的 0 / 1 值显示为中文的"未确认""已确认", "未付款""已付款", "未发货""已发货", "未归档""已归档"
select OrderID, 
OrderIsConfirm = case OrderIsConfirm when 0 then '未确认' when 0 then '已确认' end,
OrderIsPayment = case OrderIsPayment when 0 then '未付款' when 1 then '已付款' end,
OrderIsConsignment = case OrderIsConsignment when 0 then '未发货' when 1 then '已发货' end,
OrderIsPigeonhole = case OrderIsPigeonhole when 0 then '未归档' when 1 then '已归档' end
from Orders
-- 分析:普通的case语句(另外注意case语句有两种形式,对应离散和连续值的微妙差别)


-- 2. 计算0~1所有自然数之和
create function getSum() returns int	// 封装了一个函数
as
begin
	declare @n int;
	declare @sum int;
	set @n = 0;
	set @sum = 0;
	while(@n <= 100)
	begin
		set @sum += @n;
		set @n += 1;
	end
	return @sum;
end

declare @sum int
set @sum = dbo.getSum()
select @sum		-- 输出5050


猜你喜欢

转载自blog.csdn.net/m0_46202073/article/details/106502985