SQL Server数据库操作(三)

本文详细介绍SQL中的数据分组、筛选、类型转换等基本操作,深入探讨了union联合结果集、存储过程、触发器等高级特性,并讲解了ADO.NET在数据库访问中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要内容:

1)数据分组:group by

2)数据筛选:having

3)类型转换函数:cast()  convert()

4)union 联合结果集

5)插入多条记录

6)字符串函数

7)日期函数 (记忆比较细的知识点)



代码如下:

/*
快捷键 F1 表示打开帮助(要学会使用帮组文档,特别是对函数而言)

数据分组(order by与group by是不一样的)
在使用select查询的时候,有时对数据进行分组总汇,即将现有的数据按照某列来汇总统计,这是就需要用到group by语句。
分组一般和聚合函数连用。
使用聚合函数返回每一组的汇总信息。
关键是理解需求的含义:先筛选然后分组。
*/

--请从学生表中查询出每个班级的班级id和班级人数
SELECT  *
FROM    dbo.Student;

--按照某一列的数据进行分组(这一列中的数据相同的分为一组,select 后面跟的是列名),查询出所有的记录,
SELECT  StuClassId AS 班级id ,
        班级人数 = COUNT(*)
FROM    dbo.Student
GROUP BY StuClassId;

--请统计班级中男同学和女同学的人数
SELECT  StuGender ,
        人数 = COUNT(*)
FROM    dbo.Student
GROUP BY StuGender;

--请统计班级中所有的班级id和每个班级中的男同学数
SELECT  *
FROM    Student;

UPDATE  dbo.Student
SET     StuGender = '男'
WHERE   StuClassId = 2;

SELECT *  FROM dbo.Student;


UPDATE  Student
SET     StuClassId = 2
WHERE   StuName = '张诗';


SELECT  *
FROM    dbo.Student;

--更新数据,把班级id为2的所有学生的性别改成男(查询这两列数据,统计所有的性别为男的记录)
SELECT  班级id = StuClassId ,男同学数 = COUNT(*) FROM  Student WHERE StuGender = '男'GROUP BY StuClassId;

--下面的写法会报错(因为按照性别分组后,年龄字段就被合并了不能显示了,因为其他列就不存在了)
SELECT  姓名 = StuName ,
        班级id = StuClassId ,
        男同学数 = COUNT(*)
FROM    Student
WHERE   StuGender = '男'GROUP BY StuClassId;

/*
对分组以后的数据进行筛选
where与having都是对数据筛选,wher是对分组前的每一组数据进行筛选,而having是对分组后的的数据进行筛选。
where是对每条记录进行过滤的,having是对查询到的组进行过滤的。

*/
SELECT * FROM dbo.Student;

UPDATE  Student
SET    StuClassId=2
WHERE  StuName = '张慧';

SELECT  班级id = StuClassId ,
        女生人数 = COUNT(*)
FROM    Student
WHERE   StuGender = '女'
GROUP BY StuClassId
HAVING  COUNT(*) > 1; 

--查询班级人数超过两个人的班级
SELECT 班级id =StuClassId ,班级人数 = COUNT(*) FROM dbo.Student GROUP BY StuClassId HAVING  COUNT(*) > 2;

/*
sql语句的执行顺序:
	SELECT 选择的列、distinct、top 5列名
	FROM 表名
	WHERE 条件
	GROUP BY 列名
	HAVING 筛选添加
	order by 排序
*/

--查询出热销商品,销售数量列,按照商品进行分组

/*
类型转换函数: 把数字类型的字符串转换成int类型
cast函数(表达式 as 数据类型) 表达式指待转化的字符串
convert函数(数据类型,表达式,style)style指定CONVERT 函数如何转换 expression 的整数表达式
日期转字符串:将日期转化成指定格式的字符串
*/

--内部帮我们进行了类型转换
SELECT 100+'1000';
SELECT '1000'+100;

--自己进行类型转换
--使用cast进行转换
SELECT 100+CAST('1000' AS INT);

--使用convert进行转换
SELECT 100+CONVERT(INT,'1000' );
SELECT '您的班级编号为:'+CONVERT(CHAR(1),1);

--把日期转化成字符串类型
SELECT CONVERT(varchar(50),GETDATE(),120);
SELECT CONVERT(varchar(50),GETDATE(),101);

/*
union联合结果集
1)集合运算符是对两个集合操作的,两个集合必须具备相同的列数,列具备相同的数据类型(至少能够隐式转化的),
最终输出的集合的列名有第一个集合的列名来确定
2)联合union与连接join不一样
3)简单的联合结果集(老师和学生)  基本的原则:每个结果集必须具备相同的列数,每个结果集列的类型必须兼容
4)联合:将多个结果集合并成一个结果集,union 去除重复 相当于默认应用了distinct,常见应用底部汇总。
联合:把多个查询结果合并成一个 列的数量一致,对应列上的数据类型至少能够隐式类型转化
使用nuion能够去除重复,但是使用union all不能去除重复数据
5)大多数情况下,联合的时候是不需要去除重复的,同时要保持数据的顺序,所以一般建议使用union all
因为union要进行重复值的扫描,所以效率比较低。
6)使用 union all执行插入操作:一次插入多条记录。
*/

--能够查询出两个陈如水
SELECT TeaName FROM dbo.Teacher UNION ALL SELECT StuName FROM Student;
--合并重复的记录
SELECT TeaName FROM dbo.Teacher UNION SELECT StuName FROM Student;

INSERT INTO dbo.Student
        ( StuName ,
          StuGender ,
          StuAddress ,
          StuAge ,
          StuBirthday ,
          StuCardId ,
          StuClassId
        )
VALUES  ( N'陈如水' , -- StuName - nvarchar(10)
          N'男' , -- StuGender - nchar(1)
          N'河南省项城市' , -- StuAddress - nvarchar(100)
          55, -- StuAge - int
          GETDATE() , -- StuBirthday - datetime
          '412702199102181579' , -- StuCardId - varchar(18)
          1  -- StuClassId - int
        )

SELECT * FROM dbo.Student;

--查询所有年龄表中的最大年龄、最小年龄、平均年龄
SELECT 最大年龄=MAX(StuAge) FROM dbo.Student
SELECT 最小年龄=min(StuAge) FROM dbo.Student
SELECT 平均年龄=avg(StuAge) FROM dbo.Student

--此时列名是“名称”,其中的值为最大年龄、最小年龄、平均年龄。一定要特别记忆。
SELECT 名称='最大年龄',年龄=MAX(StuAge) FROM dbo.Student
UNION ALL
SELECT 名称='最小年龄', 年龄=min(StuAge) FROM dbo.Student
UNION ALL
SELECT 名称='平均年龄',年龄=avg(StuAge) FROM dbo.Student

SELECT * FROM dbo.Teacher;
--向表中插入一列
ALTER  TABLE  dbo.Teacher ADD TeaSalary int;
SELECT * FROM dbo.Teacher;
UPDATE  Teacher SET TeaSalary =1600 WHERE TeaName='陈少文';
SELECT * FROM Teacher;

INSERT INTO dbo.Teacher
        ( TeaName ,
          TeaGender ,
          TeaAge ,
          TeaBirthdat ,
          TeaAddress ,
          TeaEmail
        )
VALUES  ( N'陈少文' , -- TeaName - nvarchar(20)
          0, -- TeaGender - bit
          10 , -- TeaAge - int
          GETDATE() , -- TeaBirthdat - datetime
          N'河南省周口市' , -- TeaAddress - nvarchar(10)
          N'2586622608@qq.com'  -- TeaEmail - nvarchar(50)
        )

--查询每位老师的信息包括姓名、工资并在最后一行加上平均工资和最高工资
SELECT 教师姓名=TeaName,教师工资=TeaSalary FROM dbo.Teacher
UNION ALL
SELECT '平均工资',AVG(TeaSalary) FROM dbo.Teacher
UNION ALL
SELECT '最高工资', MAX(TeaSalary) FROM dbo.Teacher;

--一次插入多条记录如何实现
--INSERT INTO SELECTUNION ALL
SELECT * FROM dbo.Teacher;

INSERT INTO dbo.Teacher
SELECT '陈如水',0,25,GETDATE(),'中国','2586622608@qq.com',1500
UNION ALL
SELECT '陈如水',0,25,GETDATE(),'中国','2586622608@qq.com',1500
UNION ALL
SELECT '陈如水1',0,15,GETDATE(),'中国武汉','2586622608@qq.com',1504;

/*
一次性向表中插入多条记录的方法
1)把现有的表的数据复制到一个已经存在的表,对于这种复制,只能复制表中的数据以及列的名字和数据类型,但是不会复制约束。
2)如何把表中的记录备份到另外一张表中
*/

--备份表,但是约束不能备份到另外一张表中(现在只能复制表数据)
--从老师表中查询数据,把查询到的数据备份到CopyTeacher表中;表CopyTeacher不存在,在执行sql语句的时候会自动创建一张表
SELECT * INTO CopyTeacher FROM Teacher;
SELECT * FROM CopyTeacher;

--如何将表结构复制一份呢,这时只赋值了表结构
SELECT * INTO CopyTeacher1 FROM dbo.Teacher WHERE 1<>1;
SELECT TOP 0 * INTO CopyTeacher2 FROM dbo.Teacher;
SELECT * FROM CopyTeacher2;


--如何将表结构和表数据赋值一份呢
--使用insert...into...SELECT...from...
INSERT  INTO CopyTeacher2 SELECT TeaName,TeaGender,TeaAge,TeaBirthdat,TeaAddress,TeaEmail,TeaSalary FROM dbo.Teacher;
SELECT * FROM CopyTeacher2;

/*
字符串函数
len():计算字符串的长度
datalength():计算字符串所占用的字节数
lower():转化成小写
upper():转化成大写
ltrim():去掉字符串左侧空格
rtrim():去掉字符串右侧空格
截取字符串,有三个函数 left() right() substring(str,srartPosition,length)索引从1 开始
尝试使用sql帮助。----直接搜索:函数-->字符串函数
*/
PRINT LEN('碧云天黄叶地');
--一个汉字占用了两个字节
PRINT DATALENGTH('碧云天黄叶地 ');
--n表示所有的字符都是汉语,一个字符占用两个字节
PRINT DATALENGTH(N'碧云天黄叶地 ');

PRINT LOWER('Hello World!');
PRINT UPPER('Hello World!');
PRINT LTRIM('  秋色连波,波上寒烟垂');
PRINT LTRIM('秋色连波,波上寒烟垂');

--截取字符串  截取几个字符。从左边开始截取,截取五个字符
PRINT LEFT('待我长发及腰',5);

--索引是从1开始的,不要使用0或者负数
PRINT SUBSTRING('念去去千里烟波,暮霭沉沉楚天阔',1,3)

/*
日期函数
1)getDate() 获取当前日期时间
2)dateadd(datepart,number,date)计算增加以后的日期,date表示带计算的日期,number为增量,datepart表示计量单位
3)datediff(datepart,startdate,enddate) 计算两个日期之间的差额,datepart表示计量单位
4)datepart(datepart,date)返回一个日期的特定部分
5)Month()、year()、day()
*/

--日期和时间函数
PRINT getdate();
PRINT SYSDATETIME();

--从当前时间增加两百天,两百月,两百年,两百分钟,两百秒
PRINT DATEADD(DAY,200,GETDATE());
PRINT DATEADD(month,200,GETDATE());
PRINT DATEADD(year,200,GETDATE());
PRINT DATEADD(minute,200,GETDATE());
PRINT DATEADD(hour,200,GETDATE());
PRINT DATEADD(second,200,GETDATE());
PRINT DATEADD(week,200,GETDATE());

--公司给员工发奖金,入职一年以上的员工才会有奖金,如何实现
--关键是与当前时间进行比较
SELECT * FROM dbo.Teacher;
SELECT * FROM dbo.Teacher WHERE DATEADD(hour,1,TeaBirthdat)<=GETDATE();

--计算两个日期的差值 datediff() 主要是当前日期的差值
SELECT DATEDIFF(month,'2015-01-04',GETDATE())

--获取日期某部分的值
PRINT DATEPART(YEAR,GETDATE());
PRINT DATEPART(month,GETDATE());

--获取当前的年部分 含义是获取日期并截取其中的年部分
PRINT YEAR(GETDATE());
PRINT MONTH(GETDATE());


1)为什么要学习ado.net:之前我们只能在查询分析器里查看数据、操作数据,所以大家一个借鉴让用户方便的操作数据库中的数据。

2)什么是ado.net:ado.net其实是一组类库,这个类库可以让我们通过程序的方式访问数据库,就像System.io下的类操作文件一样,System.DATA这个类库就是用老操作数据库的,它提供了统一的编程接口。

3)学习目的:通过应用程序访问数据库。

4)ado.net类库组成:(学习这几个类的api,常用类)
Connection:用来连接数据库(负责和数据库建立网络连接)
Command:用来执行sql语句(负责把sql语句发送给数据库服务进行执行)DataReader:只读只进的结果集,一条一条的读取数据(把数据库服务器的执行结果获取到本地)DataAdapte:一个封装了上面三个对象的对象(一句话搞定上面的三个对象)
场景: 当在某个代码段中使用了类的实例,而希望无论因为什么原因,只要离开了这个代码段就自动调用这个类实例的Dispose。 要达到这样的目的,用try...catch来捕捉异常也是可以的,但用using也很方便。
        } 
C# typeof() 是做什么用的

DataSet:数据集,临时数据库,断开式数据操作。

5)ado.net访问数据库的方式
方式一:
连接数据用Connection
执行sql语句用Command
执行完毕后,将结果一一返回用DataReader
方式二:
使用DataAdapter+DataSet这种方法的本质还是通过Connection、Command、DataReader将数据全部取出来,然后放到DataSet中。

ado.net连接池
1)由于每次正常连接数据库都至少会执行三个操作(登录数据库服务器;执行操作;注销用户);所以每次通过SqlConnection向数据库服务器申请一个连接比较耗时。ado.net默认启动了连接池。
2)有没有连接池的差别,通过事件查看器查看效果。为了解决这个问题:ado.net采用了连接池的概念。
3)如何清空连接池?Connection的静态方法ClearAllPools()、ClearPool()
4)什么情况下需要禁用连接池?一般不需要禁用,尤其是asp.net之类的程序,n多个用户频繁访问,但是大多数用户访问时采用的都是同一个连接字符串。但是如果某个应用程序有多个客户端,每个客户端访问时采用的都是各自连接的字符串,这是如果采用连接池,虽然每次打开连接的速度回变快,但是由于池的问题同时会保存多个打开的连接对象。
使用tcp/ip协议,中间需要进行三次握手。

1)第一次打开连接会创建一个连接对象;
2)当这个连接关闭时,调用Close()方法,会将当前的连接对象放入到连接池中;
3)下一个连接对象,如果连接字符串与池中现有连接对象的连接字符串完全一样,则会使用池中现有的连接对象,而不会重新创建一个。
4)只有对象调用Close()的时候,连接对象才会放置到连接池中;如果一个连接对象一直在使用,则下次在创建一个连接对象时,发现连接池中没有可用的,也会创建一个新的连接对象。
5)在连接池中的连接对象,如果过一段时间没有被访问,则自动销毁。

连接对象最晚打开,最早关闭。
如何禁用连接池?
App.config

九:using关键字的使用
using语句,定义一个范围,在范围结束时处理对象。 
场景: 
当在某个代码段中使用了类的实例,而希望无论因为什么原因,只要离开了这个代码段就自动调用这个类实例的Dispose方法。 
要达到这样的目的,用try...catch来捕捉异常也是可以的,但用using也很方便。

ado.net数据库操作(三)
对类属性方法的理解的理解
如何对值进行存储?  对实体模型不太懂n

ctrl+. 这个万能键  不太理解
直接输入prop,然后连按两下tab.会自动生成get/set.只需要修改下属性名即可。
自动生成toString方法的快捷键

override  重写父类中的方法
      
 public override string ToString()
        {
            return base.ToString();

会有自能提示的

ExecuteScalar()内部就是ExecuteReader()实现的,只获取了第一行记录。



DataTable

查询--->查询选项--->高级--->IO和time。
asc升序排列:“order by 列名 排序方式

对每一行记录进行编号,查询指定页面的第一条数据的编号与最后一条数据的编号,between...and...关键字的使用
连接查询和联合查询的区别:联合是把表中的行连接起来,连接是把表中的列连接起来。如何把表中的列关联起来?on是指筛选条件。
连接查询,连接查询使用的关键字join。
连接查询主要用于解决什么样的问题呢?把多张表中的数据(列)查询到一个结果集中。
update...set...where
分析需求,看看是需要查询几张表中的数据。
not in (只能是某一列)子句的使用
左外连和右外连查询互换表的位置就可以啦

核心名词
连接查询、左表、右表、内连接、外连接、笛卡尔积、on子句数据筛选、自连接


----------------------————————————————————————————————————————————————————————————————————>
连接查询:关键是看两张表的主外键关系
内连接:inner join:多表内连接,无论连接几张表,每次执行都是两张表进行连接。在多张表中进行查询,结果在一张表中。
外连接:左外连接(left outer join) 有外连接(right outer join)。左表和右表。
连接查询的基本执行步骤:1)笛卡尔积,好好理解这个概念2)应用on筛连接选器3)添加外部行,到此from执行完毕。
当使用连接查询的时候,如果同时要指定查询的条件,那么一定要使用where子句,不要直接在on条件后面跟and来编写其他查询条件。
内连接执行的过程是:先进行笛卡尔积,然后进行on筛选条件,如果是外连接,就添加对应表中的数据。添加外部行。

外连接的执行步骤:
1)构建笛卡尔积;
2)根据left join on条件进行行数据的筛选;
3)因为是外连接,所以要显示左表中的所有记录,所以接下来要进行"添加外部行"。把左表中哪些没有筛选出来的哪些数据再添加到当前的查询结果集中

自连接:
外连接:是指多张表进行连接。
什么叫自连接:自己和自己连接,把表中的所有列都复制一份。
select * from TblArea as t1,TblArea as t2;从这两张表中进行查询
对表起别名特别有用;对列起别名,汉字好理解。
关键是对逻辑关系的理解,弄清楚了这个,代码很好写的。

查询所有学生的姓名、年龄以及所在班级:
分析:需要从学生表和班级表中进行查询。需在在多张表中进行查询,这就需要用到连接。
select t1.tsName,t1.tsAge ,t2.tsClass 
FROM Student as ti 
inner join Class as t2 
on t1.tsClass=t2.tClassId  这是连接条件?

查询年龄超过20岁的所有学生的姓名、年龄以及所在班级:
select t1.tsName,t1.tsAge ,t2.tsClass 
FROM Student as ti 
inner join Class as t2 
on t1.tsClass=t2.tClassId 
where tsAge > 20

请查询出所有同学的姓名,年龄,英语成绩,数学成绩:(但是某些学生没有参加考试)
如何理解左外连接:如果找不到对应的值,则值为空。left join关键字两边都有一张表,把左边表中的所有数据都显示出来;
同时右边的表,如果存在就显示出来,如果找不到匹配的数据,就显示为null。
出现在left join左侧的表就是左表,出现在left join右侧的表就是右表。
内连接是只显示哪些两张表中都匹配的数据。

模糊查(多条件查询):使用带参数的SQL语句.比如根据作者查询数据,根据年份查询书籍。
使用 like关键字进行模糊查询。动态拼接sql语句,看看用户输入了哪些查询条件或者前台传递过来哪些查询关键字。
1)如果用户没有输入任何条件,那就直接查询出所有的记录。2)如果用户输入了条件,则根据用户输入的条件动态拼接sql语句。
对应项目开发中的搜索模块

视图概述:主要用于封装复杂查询的。
如何创建视图?如何删除视图?视图的作用是什么?什么时候使用视图? 注意这四个问题.

数据是怎么存储的?
视图是一张虚拟表,它表示一张表的部分数据或者多张表的综合数据,其结构和数据是建立在对表的查询基础上。
视图在操作上和数据表没有什么区别,但是两则的差异是其本质不同:数据表是实际存储记录的地方,然而视图并不保存任何记录。
相同的数据表,根据不同用户的不同需求,可以创建不同的视图(不同的查询语句);
视图的目的是方便查询,所以一般情况下不能对视图进行增删改。
优点:筛选表中的行/降低数据库的复杂程度(调用视图,直接一句话进行查询),防止未经许可的用户访问敏感数据(看不到表名和表字段)。
视图其实是对复杂的查询语句的封装。直接调用视图就可以进行查询了。
View 关键字的封装
create View vw_TblArea as ....  create View 视图名称 as ....
select * from vw_TblArea; 视图相当于别名
SQL Server下有视图结点
视图只能写(保存)查询语句,而存储过程就像方法一样,特别灵活。可以使用存储过程替代视图。
视图中不能有参数。
如果视图中的查询语句中包含了重名的列(多个表之间)必须给列起别名。
普通视图并不存储数据(虚拟表),访问的是真实表中的数据。

T-SQL编程:(先声明在赋值)
声明局部变量:DECLARE @变量名 数据类型 [=默认值] 
例如:declare @name varchar(20); declare @age int;

赋值:
set @变量名=值; set用于普通的赋值
select @变量名=值; 用于从表中查询数据并赋值,可以一次给多个变量赋值。
例如:set @name=‘张三’; set @id=1; select @name=sName FROM Student where sId=@id

输出变量的值:(打印变量的值)
1)select以表格的方式输出,可以同时输出多个变量。select @name,@id
2)print以文本的方式输出,一次只能输出一个变量的值。print @name;print @id
print @name,@id; 这样写是错误的。

变量分类:
1)局部变量:局部变量必须以标记@作为前缀,比如 @Age int;局部变量必须先声明,在赋值。
2)全局变量:全局变量的定义必须以@@作为前缀,如 @@version 全局变量有系统维护和定义,我们只能读取,不能修改全局变量的值
全局变量又称为系统变量。两个@@符号开头的一半都是系统变量。

SQL中常用的全局变量:
@@version:SQL Server的版本信息
@@SERVERNAME:本地计算机的名称
@@TRANSCOUNT:当前连接打开的事务数。
@@rowcount:受上一个SQL语句影响的行数。
@@max_connections:可以创建的同时连接的最大数目。
@@language:当前使用的语言的名称。

在sql里面怎么写循环?
1)sql里面是没有for循环的,使用while循环。如何使用while循环输出100句hello?
2)在循环结构里面可以使用break,continue

在sql里面怎么写if-else?
IF(条件表达式)
begin  相当于C#里面的{
end  相当于C#里面的}
else
begin  相当于C#里面的{
end  相当于C#里面的}

事务
为什么需要事务?
指访问并可能更新数据库中各种数据项的一个程序执行单元,也就是说多个sql语句,必须作为一个整体执行。
这些sql语句作为一个整体一起向系统提交,要么都执行,要么都不执行。
语法:
开始事务 begin transaction
提交事务 commit transaction
回滚事务 rollback transaction
判断某条语句是否出错,使用全局变量@@error

事务分类:
自动提交事务:数据库自动来做,不需要用户考虑任何事情。insert into Teacher values();默认情况下sql使用的是自动提交事务。
隐式事务:set implicit transaction  on | off  每次执行一条sql语句的时候,数据库会自动帮助我们打开一个事务,但是需要我们手动提交事务或者回滚事务。不手动提交或者回滚,sql语句执行不能成功,显示一直正在执行中。
显示事务:需要开发人员手动打开、回滚、提交事务。

事务的几个特性:
原子性、一致性、隔离性(多个事务之间)、持久性:事务完成后,它对于系统的影响是永久性的,该修改即使出现系统故障也将一直保持。

在转账之前最好通过if-else判断,不要让程序发生异常或者错误。

如何保证两条语句要么同时执行成功要么同时执行失败?使用事务来保证。
把要执行的代码放置到一个事务里面;如果其中的某一行行执行出错,那就让代码回滚。
1)打开一个事务  begin transaction
2)declare @sum int;每执行一条sql语句,就记上这样一句话:set @sum=@sum+@@error。只要有人恶化一条sql语句出错,sum的值就不是0。
3)if @sum<>0 说明其中的代码执行出错。
begin
    说明其中的代码执行出错。
    直接进行回滚
    rollback;
end
else
begin
    //如果程序执行没有出错,就进行提交代码。
    commit
end

存储过程:
1)其实就是在数据库中运行方法(函数),它和c#里面的方法一样,由存储过程名/存储过程参数组成/可以有返回结果。
2)if--else、while、变量、insert等,都可以在存储过程中使用。
3)使用存储过程的优点:执行速度快,在数据库中保存的存储过程语句都是编译过的。允许模块化程序设计,类似方法的复用。提高系统安全性,防止SQL注入;减少网络流通量,只要传输存储过程的名字。
4)系统存储过程:由系统定义,存放在master数据库中。名称以“sp_”开头或者“xp_”开头,自定义的存储过程可以以usp_开头。
5)自定义的存储过程:由用户在自己的数据库中创建的存储过程usp。
6)使用存储过程也有缺点:如果在服务器端写了过多的存储过程,当用户访问量比较大时,所有的压力都有数据库来承担了。把业务逻辑也写到存储过程里面了,业务逻辑应在在C#代码里面的。一旦服务器出现瓶颈,优化起来比较困难。注意控制使用存储过程的数量。

存储过程和函数在本质上没有区别。函数只能返回一个变量,而存储过程可以返回多个。一般来说存储过程实现额功能要复杂一些,而函数实现的功能针对性比较强。
把存储过程当做一个独立的部分来执行。
把常用的代码封装到存储过程里面,直接调用存储过程名就好了。
usp_开头一般是用户存储过程。
存储过程内部就是一段sql代码。
order by 索引 :按照第几列进行排序。

系统存储过程:直接可以拿来用。凡是以sp开头的一般都是存储过程。
sp_databases:列出服务器上所有的数据库。
sp_helpdb:报告有关指定数据库或所有数据库的信息。
sp_renamedb:更改数据库的名称。
sp_tables:返回当前环境下所有的数据表(use关键字的使用)。
sp_columns:返回某个表列的信息。
sp_help:查看某个表的所有信息。
sp_helpconstraint:查看某个表的约束。
sp_helpindex:查看某个表的索引。
sp_stored_procedures:列出当前环境下所有的存储过程。
sp_password:添加或修改登录账户的密码。
sp_helptext:显示默认值、未加密的存储过程、用户定义的存储过程、触发器或试图的实际文本。(获取存储过程的源代码)

如何执行存储过程?
如果是系统存储过程,直接选中存储过程的名字,可以直接执行;
对于用户自定义的存储过程,存储过程名之前要加exec:exec 存储过程名。


如何创建自定义的存储过程?
定义存储过程的语法:
create proc[edure] 存储过程名
@参数1 数据类型=默认值 output,
@参数n 数据类型=默认值 output
as 
    sql语句
参数说明:参数可选,参数分为输入参数、输出参数,输入参数允许有默认值。

1)存储过程的分类:     系统存储过程与用户自定义存储过程
2)执行存储过程的关键字:    exec 存储过程名 [参数] ;创建存储过程的语句:CREATE PROC usp_say_he。
3)用户自定义存储过程一般以usp开头,见名知意,要使用关键字表示,这个存储过程是操作哪张表的?
4)存储过程英语: procedure
5)创建执行过程----->执行存储过程(调用存储过程),这是两个过程,千万别忘了。
6)自定义存储过程的标准语法:create proc 存储过程名 as begin 具体的业务逻辑 end。
7)如何删除存储过程: drop proc 存储过程名。
8)如何查看某个存储过程的源代码?    exec sp_helptext 'sp_databases';

1)如何创建带参数的存储过程;
2)如何设置存储过程参数的默认值?
3)如何调用带参数的存储过程?

如何通过ado.net来调用存储过程?
1、通过ado.net调用存储过程与调用带参数的sql语句的区别
1)把sql语句变成存储过程名.
2)设置SqlCommand对象的CommandType为CommandType.StoredProcedure.
3)根据存储过程的参数来设置输出参数的Direction属性.
4)如果有输出参数,需要设置输出参数的Direction属性为Direction=ParameterDirection.Output.

2、如果是通通过调用Command对象的ExecuteReader()方法来执行该存储过程的,
那么想要获取输出参数,必须等到关闭reader对象后,才能获取输出参数的值。

3、为什么执行存储过程的时候,需要设置CommandType.StoredProcedure.设置此属性,到底做了什么事情?

赋值语句:select与set的区别
1)如果想要把一个查询结果赋值给变量,则必须用()括起来
declare @a int
set @a=(select count(*) from Teacher)
select @a=count(*) from Teacher
print @a;
2)print每次只能打印一个变量的值。
set @a=1;
select @a=1;
3)下面这种情况是有问题的
declare @i int;
set @i=(select tsage from Teacher)
print @i;
因为查询结果不是一个数据,而是一列数据,所以这样赋值会报错。
当通过set为变量赋值的时候,如果查询语句返回的不是单个值,那么就会报错。

下面这种写法不会报错的。
declare @i int;
select @i=(select tsage from Teacher)
print @i;
但是当通过select为变量赋值的时候,如果查询语句返回的不止一个值,那么会将最后一个结果赋值给该变量。
相对而言,set赋值更严谨一些,select赋值更灵活一点。

静态类构造函数的特点:
static MyClass(){
}
1)要使用static关键字修饰。
2)只执行一次,在第一次使用静态类之前执行一次。
3)静态构造函数不重载。

案例:把事务转账封装到一个存储过程里,并通过ado.net调用该存储过程。

如何通过存储过程对表实现增删改查?

sql里面的try...catch...

同一个SqlParameter不能同时用于多个SDqlCommand对象,否则会报错。

触发器:
trigger(枪上的扳机)
1)作用是:自动化操作,减少了手动操作以及出错的几率。
2)理解:触发器是一种特殊的存储过程,在SQL内部把触发器看做是存储过程但是不能传递参数。
3)一般的存储过程通过存储过程名被直接调用,但是触发器主要是通过事件进行触发而执行。
4)处罚器是一个功能强大的工具,在表的数据发生变化时自动强制执行。触发器还可以用于Sql server约束、默认值和规则的完整性检查
还可以完成难以用普通约束实现的复杂功能。
5)什么是触发器呢? 在SQL Server里面也就是对某一个表的某种操作,处罚某个条件,从而执行的一段程序。触发器是一个特殊的存储过程。
可以理解为一个特殊的存储过程。触发器不是用户自己调用的,而是在某种情况下自动执行的。

触发器分类:
1)DML触发器:数据操作 删除、更新、插入; after触发器(for)  instead of触发器()
2)DDL触发器:数据定义 create tablecreate databasealter; drop比如当一张表创建以后,立即出发一个事情。
3)inserted表与deleted表,这两张表是做什么的?inserted表包含新数据,insert、update触发器会用得到。
deleted表包含旧数据,delete、update触发器会用到。












































    








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值