SQL Server面试集合

数据库三范式是什么?

第一范式:字段不能有冗余信息,所有字段都是必不可少的。
第二范式:满足第一范式并且表必须有主键。
第三范式:满足第二范式并且表引用其他的表必须通过主键引用。

1、索引的作用?和它的优点缺点是什么?

索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。

2、说一下SQLServer中索引的两种类型?

聚簇(或者叫做聚集,cluster)索引和非聚簇索引。

字典的拼音目录就是聚簇(cluster)索引,笔画目录就是非聚簇索引。这样查询“G到M的汉字”就非常快,而查询“6划到8划的字”则慢。

聚簇索引是一种特殊索引,它使数据按照索引的排序顺序存放表中。聚簇索引类似于字典,即所有词条在字典中都以字母顺序排列。聚簇索引实际上重组了表中的数据,所以你只能在表中建立一个聚簇索引。

3、触发器的作用?

触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。

4、什么是事务?什么是锁?

事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性

锁:在DBMS中,锁是实现事务的关键,锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。当然锁还分级别的。

5、事务是什么?

事务是作为一个逻辑单元执行的一系列操作,一个逻辑工作单元必须有四个属性,称为 ACID(原子性、一致性、隔离性和持久性)属性,只有这样才能成为一个事务:

1)原子性

事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。

2)一致性

事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。

3)隔离性

由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。

4)持久性

事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。

6、什么叫视图?游标是什么?

视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。

游标:是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。

7、什么是SQL注入式攻击?

所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。

8、写出一条Sql语句:取出表A中第31到第40记录(SQLServer,以自动增长的ID作为主键,注意:ID可能不是连续的)

解1: select top 10 * from A where id not in (select top 30 id from A)

解2: select top 10 * from A where id > (select max(id) from (select top 30 id from A )as A)

9、横表、纵表转换

纵表结构 TableA
在这里插入图片描述
横表结构 TableB
在这里插入图片描述
先理解:

select Name(case Course when ‘语文‘ then Grade else 0 end) as 语文,

 (case Course when ‘数学‘ then Grade else 0 end) as 数学,

 (case Course when ‘英语‘ then Grade else 0 end) as 英语

from TableA

然后理解标准答案:

select Namesum(case Course when ‘语文‘ then Grade else 0 end) as 语文,

sum(case Course when ‘数学‘ then Grade else 0 end) as 数学,

sum(case Course when ‘英语‘ then Grade else 0 end) as 英语

from TableA

group by Name

横表转纵表的"SQL"示例

横表结构: TEST_H2Z

  ID      姓名    语文        数学       英语     

  1       张三     80         90         70           

  2       李四     90         85         95         

  3       王五     88         75         90      

转换后的表结构:

  ID     姓名     科目     成绩 

  1       张三     语文     80 

  2       张三     数学     90 

  3       张三     英语     70 

  4       李四     语文     90 

  5       李四     数学     80   

  6       李四     英语     99 

  7       王五     语文     85 

  8       王五     数学     96 

  9       王五     英语     88  

横表转纵表SQL示例:

SELECT   姓名,'语文'   AS     科目,语文   AS   成绩   FROM   TEST_H2Z   UNION   ALL 
SELECT   姓名,'数学'   AS     科目,数学   AS   成绩   FROM   TEST_H2Z   UNION   ALL 
SELECT   姓名,'英语'   AS     科目,英语   AS   成绩   FROM   TEST_H2Z
ORDER BY 姓名,科目 DESC

10、删除姓名、年龄重复的记录

Id  name  age  salary

1   yzk    80  1000

2   yzk    80  2000

3   tom    20  20000

4   tom    20  20000

5   im     20  20000

//取得不重复的数据

select * from Persons where Id in (SELECT MAX(Id) AS Expr1 FROM Persons GROUP BY Name, Age)

根据姓名、年龄分组,取出每组的Id最大值,然后将Id最大值之外的排除。

删除重复的数据:

delete from Persons where Id not in (SELECT MAX(Id) AS Expr1 FROM  Persons GROUP BY Name, Age)

11、表操作查询

表一:student_info
在这里插入图片描述
表二:curriculum
在这里插入图片描述
表三:grade
在这里插入图片描述题目:
条件查询:

1、在GRADE表中查找80-90份的学生学号和分数

select 学号,分数 from grade where 分数 between 80 and 90

2、在GRADE 表中查找课程编号为003学生的平均(avg)分

  select avg(分数) from grade where 课程编号='003'

3、在GRADE 表中查询学习各门课程的人数

select 课程编号,count(学号) as 人数 from grade group by 课程编号

4、查询所有姓张的学生的学号和姓名

  select  姓名,学号 from student_info where 姓名 like '张%'

嵌套查询:

1、 查询和学号’0001’的这位同学性别相同的所有同学的姓名和出生年月

  select 姓名,出生年月 from student_info where 性别 in (select 性别 from student_info where sno = '0001')

2、 查询所有选修课程编号为0002 和0003的学生的学号、姓名和性别

 select 学号,姓名,性别 from student_info where 学号 in (select 学号 from grade where 课程编号 = '0002' and 学号 in (select 学号 from grade where 课程编号  =  '0001'))

3、 查询出学号为0001的学生的分数比0002号学生最低分高的课程编号的课程编号和分数

 select 课程编号, 分数 from grade where 学号 = '0001' and 分数 > (select min(分数) from grade where 学号 = '0002')

多表查询:

1、 查询分数在80-90分的学生的学号、姓名、分数

select student_info.学号,student_info.姓名,grade.分数 from student_info,grade where grade.分数 between 80 and 90

2、 查询学习了’C语言’课程的学生学号、姓名和分数

select student_info.学号,student_info.姓名,grade.成绩 from student_info,grade,curriculum where student_info.学号 = grade.学号 and grade.课程号 = curriculum.课程号 and curriculum.课程名 = 'C语言'

3、 查询所有学生的总成绩,要求列出学号、姓名、总成绩,没有选课的学生总成绩为空。

select grade.学号,student_info.姓名,sum(grade.成绩) as 总成绩 from student_info,grade where grade.学号 = student_info.学号 group by grade.学号,student_info.姓名

12、本题用到下面三个关系表:

CARD     借书卡:   (CNO 卡号,NAME  姓名,CLASS 班级)

BOOKS    图书:     (BNO 书号,BNAME 书名, AUTHOR 作者,PRICE 单价,QUANTITY 库存册数 )

BORROW   借书记录: (CNO 借书卡号,BNO 书号,RDATE 还书日期

备注:限定每人每种书只能借一本;库存册数随借书、还书而改变。

要求实现如下处理:

写出自定义函数,要求输入借书卡号能得到该卡号所借书金额的总和:

CREATE FUNCTION getSUM
(
@CNO int
)
RETURNS int
AS
BEGIN
    declare @sum int
    
    select @sum = sum(price) from BOOKS where bno in (select bno from BORROW where cno = @CNO)

    return @sum
END
GO

找出借书超过5本的读者,输出借书卡号及所借图书册数。

select CNO,count(BNO) as 借书数量 from BORROW group by CNO having count(BNO) > 3

查询借阅了"水浒"一书的读者,输出姓名及班级。

select name,class from card where cno in( select cno from borrow where bno in(select bno from BOOKS where bname ='水浒'))

查询过期未还图书,输出借阅者(卡号)、书号及还书日期。

select CNO,BNO,RDATE from borrow where getdate() > RDATE

查询书名包括"网络"关键词的图书,输出书号、书名、作者。

select bno,bname,author from books where bname like '网络%'

查询现有图书中价格最高的图书,输出书名及作者。

select bname,author from books where price in(select max(price) from books  )

查询当前借了"计算方法"但没有借"计算方法习题集"的读者,输出其借书卡号,并按卡号降序排序输出。

select cno from borrow where bno in (select bno from books where bname='计算方法') and cno not in ( select cno from borrow where bno in(select bno from books where bname='计算方法习题集')) order by cno desc

SELECT a.CNO

FROM BORROW a,BOOKS b

WHERE a.BNO = b.BNO AND b.BNAME = N'计算方法'

    AND NOT EXISTS(

        SELECT * FROM BORROW aa,BOOKS bb

        WHERE aa.BNO = bb.BNO

            AND bb.BNAME = N'计算方法习题集'

            AND aa.CNO = a.CNO )

ORDER BY a.CNO DESC

将"C01"班同学所借图书的还期都延长一周。

update borrow set rdate = dateadd(day,7,rdate) from BORROW where cno in(select cno from card where class = '一班')

从BOOKS表中删除当前无人借阅的图书记录。

DELETE A FROM BOOKS a

WHERE NOT EXISTS(

    SELECT * FROM BORROW

    WHERE BNO = a.BNO )

如果经常按书名查询图书信息,请建立合适的索引。

CREATE CLUSTERED INDEX IDX_BOOKS_BNAME ON BOOKS( BNAME )

在BORROW表上建立一个触发器,完成如下功能:如果读者借阅的书名是"数据库技术及应用",就将该读者的借阅记录保存在BORROW_SAVE表中(注:ORROW_SAVE表结构同BORROW表)

CREATE TRIGGER TR_SAVE ON BORROW

FOR INSERT,UPDATE

AS

IF @@ROWCOUNT  > 0

INSERT BORROW_SAVE SELECT i.*

FROM INSERTED i,BOOKS b

WHERE i.BNO = b.BNO

AND b.BNAME = N'数据库技术及应用'

建立一个视图,显示"力01"班学生的借书信息(只要求显示姓名和书名)。

CREATE VIEW V_VIEW

AS

select name,bname

from  books,card,borrow

where borrow.cno = card.cno and borrow.bno = books.bno and class='一班'

查询当前同时借有"计算方法"和"组合数学"两本书的读者,输出其借书卡号,并按卡号升序排序输出。

select a.cno from borrow a,borrow b

where a.cno = b.cno and

a.bno in(select bno from books where bname = '计算方法') and

b.bno in(select bno from books where bname = '组合数学')

order by a.cno asc

SELECT a.CNO

FROM BORROW a,BOOKS b

WHERE a.BNO = b.BNO

 AND b.BNAME IN('计算方法','组合数学')

GROUP BY a.CNO

HAVING COUNT(*) = 2

ORDER BY a.CNO asc

用事务实现如下功能:一个借书卡号借走某书号的书,则该书的库存量减少1,当某书的库存量不够1本的时候,该卡号不能借该书

alter PROCEDURE pro_jieshu

 @cno int,

 @bno int,

 @date datetime

AS

BEGIN

begin tran

declare @quantity int

select @quantity = quantity from books where bno = @bno

  insert into borrow values(@cno,@bno,@date)

  update books set quantity = @quantity-1 where bno = @bno

if(@quantity > 0)

  begin

   commit tran

  end

else

  begin

   print '已无库存'

   rollback

  end

END

GO

用游标实现将书号为‘A001’的书本的价格提高10元

declare @bno int
declare @bname nvarchar(50)
declare @author nvarchar(50)
declare @price int
declare @quantity int
declare mycursor cursor for select * from books
open mycursor
fetch next from mycursor into @bno,@bname,@author,@price,@quantity
while(@@fetch_status=0)
  begin
      if(@bno=2)
       begin
        update books set price=@price+10 where current of mycursor
       end
     fetch next from mycursor into @bno,@bname,@author,@price,@quantity
  end
close mycursor
deallocate mycursor
  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值