当前位置: 首页 > news >正文

第三阶段数据库-10:存储过程,事务,异常,视图,自定义函数,触发器,N关键字

1_存储过程

(1)存储过程就是封装一段SQL语句,让SQL语句当成一个整体(编译过),可以直接调用整体,提高性能

(2)特点:

  • 类似于C#中方法。方法名,方法参数列表,返回值,输入参数in,输出参数out

  • 存储过程也有参数,也有返回值,输入参数,输出参数

--1.判断某个存储过程是否存在 如果已经存在 先删除 再创建
if exists (select * FROM sys.procedures where name ='p_studentinfo_insert')
drop procedure p_studentinfo_insert
go
-- 2.定义存储过程  Procedure 缩写 proc
create proc  p_studentinfo_insert--参数列表,定义格式 参数名称 参数类型  每个参数以英文逗号隔开,最后一个参数不加逗号--输入参数(类似于C#中形式参数)@StudentName varchar(50),@Score int,--输出参数: 必须赋值, 标志名:output@ReturnValue int output
as
begin--begin 和 end 之间存储的是业务逻辑,将来业务逻辑可以是复杂的业务逻辑insert into StudentInfo(StudentName,Score) values(@StudentName,@Score);--@@rowcount; sql执行时影响的行数set @ReturnValue= @@ROWCOUNT;return 100;
end
go
-- 在 sql server 中调用存储过程
-- execute  简写  exec 
declare @rv int-- 接收输出参数,受影响的行数
declare @return int-- 接收输出参数,return出的100
exec  @return =  p_studentinfo_insert '吴亦凡666',82,@rv output
print @rv;
print @return;

(3)在C#中调用存储过程

//1.拼接存储过程使用的where条件
string where = string.Empty;
if (!string.IsNullOrWhiteSpace(txtStudentName.Text.Trim()))
{where += $" and StudentName like '%{txtStudentName.Text.Trim()}%'";
}
if (nudScoreStart.Value > 0)
{where += $" and Score >={nudScoreStart.Value}";
}
if (nudScoreEnd.Value > 0)
{where += $" and Score <={nudScoreEnd.Value}";
}
//2.设置参数
SqlParameter[] sqlParameters = new SqlParameter[]
{new SqlParameter("@currentPage",SqlDbType.Int),new SqlParameter("@pageSize",SqlDbType.Int),new SqlParameter("@where",SqlDbType.VarChar),new SqlParameter("@totalPage",SqlDbType.Int),
};
//输入参数
sqlParameters[0].Value = CurrentPage;
sqlParameters[1].Value = PageSize;
sqlParameters[2].Value = where;
//输出参数 不需要赋值
sqlParameters[3].Direction = ParameterDirection.Output;
//3.调用存储过程
//CommandType.StoredProcedure 存储过程
DataSet ds = SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, "p_studentinfo_select", sqlParameters);
//4.绑定数据源
dataGridView1.DataSource = ds.Tables[0];
ToTalPage = Convert.ToInt32(sqlParameters[3].Value);
lblPageAndTotalPage.Text = $"{CurrentPage} / {ToTalPage}";

2_事务

(1)事务:是一个整体,多个SQL语句在一个整体内完成,比如:一个整体中包含一个查询,一个更新, 一个删除语句,事务可以保证这三个语句要么同时成功,要么同时失败。不会出现一部分成功,一部分失败的情况。事务保证的是数据的一致性。

(2)raiserror和 throw都是用于抛出异常和生成错误消息的函数

@@error 语句的错误编号。若语句执行成功,返回0

--1.开始事务 事务把很多的业务逻辑当成一个整体来执行 
begin  transaction 
begininsert into StudentInfo(StudentName,Score) values ('吴亦凡123',97);insert into StudentInfo(StudentName,Score) values ('吴亦凡456',99);update  StudentInfo set  StudentName='吴亦凡666',Score=12 where StudentId = 20;--,raiserror 和 throw 都是用于抛出异常和生成错误消息的函数 raiserror('发生了一个错误',16,1);
end
​
-- !=   <>  不等于
--   @@error 语句的错误编号。若语句执行成功,返回0;
if @@error <>  0
begin rollback tran  --2.回滚事务(失败)print '执行事务失败'
end
else
begin commit tran  --3.提交事务)成功print '执行事务成功'
end

(3)语法如下: ‌开始事务‌:使用BEGIN TRANSACTION或BEGIN TRANSACTION。 ‌提交事务‌:使用COMMIT TRANSACTION。 ‌回滚事务‌:使用ROLLBACK TRANSACTION‌。

(4)事务的隔离级别(了解) SQL Server提供了多种事务隔离级别,用于控制并发事务之间的可见性和锁行为。常见的隔离级别包括: ‌READ COMMITTED‌:默认级别,只能读取已提交的数据 ‌READ UNCOMMITTED‌:允许读取未提交的数据(脏读) ‌REPEATABLE READ‌:保证在事务中多次读取同一数据时结果一致 ‌SERIALIZABLE‌:最高隔离级别,事务完全隔离,避免并发问题‌

3_捕获异常

begin trydeclare @i int;set @i = cast('abc' as int);print @i
end try
begin catchprint '转换失败'
end catch
​
--事务中捕获异常
begin  tran 
begin trydelete from  StudentInfo where StudentId =10;raiserror('一个错误',12,1);print '全部逻辑成功,就提交';commit tran 
end try
begin catchprint '任意一个逻辑失败,就回滚'rollback tran 
end catch

4_视图

(1)相当于时一个 '临时表' 就是虚拟表 它时由多个表组成的结果集,平时建议只对视图进行查询操作,增 删 改 应该应用真实的表结构

--视图 view  
if exists (select table_name from infomation_schema.views where table_name = N'v_studentinfo') 
drop View v_studentinfo
go
​
create view v_customerInfo
as
select C.CustomerId,C.CustomerName,case C.Sex when 1 then '男' else '女' end as SexName1,case C.Sex when 1 then '男' when 0 then '女'else '未知' end as SexName2,
C.Age,C.Phone,
A.ProvinceName+A.City+A.Area+A.DetailAddress as AddressDetail 
from  CustomerInfo as C left join AddressInfo as A 
on C.AddressId=A.AddressId
go
--查询视图
select  * from  v_studentinfo;

5_自定义函数

(1)示例

-- 自定义函数
if OBJECT_ID('dbo.f_add', 'FN') IS NOT NULLdrop  function f_add
go
​
create function f_add(@x int , @y int)
returns int--返回值类型
as 
beginreturn @x+@y;
end
go
​
--调用自定义函数
declare  @r int;
-- database owner   数据库拥有者
select @r  =   dbo.f_add(10,10)
print @r;

(2)一些内置的函数

select convert(varchar(10),getdate(),121)
select dateadd(month, 1, '20240830');
select dateadd(year, 1, getdate());
select power(2,3)
select ceiling(2.1)
select floor(2.9)
select round(4.6,0,0)
SELECT ROUND(123.4545, 2), ROUND(163.45, -2);  
SELECT ROUND(150.75, 0);  
SELECT ROUND(150.75, 0, 2);  
select left('hello',3)
select right('hello',3)
--截取,查索引,合并(串联),转换大写,转换小写,去空白,格式化,替换。
select substring('hello',1,3)
select upper('hello');
select lower('HELLO');
select ltrim('   hello')
select rtrim('hello   ')
select trim('   hello   ')
select reverse('hello');
select char(1)
select char( ascii('a') )
select 'abc'+'def'
select concat('hello',' world','how',' are',' you')

6_触发器

if exists (select * from sys.triggers where name = 'tri_studentinfo_insert')
drop trigger tri_studentinfo_insert;
​
create trigger   tri_studentinfo_insert on StudentInfo for insert 
as
print '我是向StudenInfo中插入数据的时候执行的触发器'
go
​
update StudentInfo set StudentName = 'ABC' where  StudentName='张三69'
insert into StudentInfo (StudentName,Score) values ('abc',90);

7_N关键字

(1)在 SQL Server 中,N 前缀用于表示其后跟的字符串是一个 Unicode 字符串字面量(nvarchar 类型),而不是普通的非 Unicode 字符串字面量(varchar 类型)。

'Some text'  --普通字符串,类型为 varchar
N'Some text' --Unicode 字符串,类型为 nvarchar

(2)需要N 前缀的原因?关键区别

varvhar 和 nvarchar 的根本区别在于字符编码和存储方式:

特性VARCHAR (非 Unicode)NVARCHAR (Unicode)
编码方式使用数据库的代码页(如 CP1252, GB2312)使用 Unicode 标准(UCS-2/UTF-16)
存储空间每个字符占 1-2 字节(取决于代码页)每个字符占 2 字节(基本多语言平面)
字符支持仅限于特定代码页定义的字符集支持全球几乎所有语言的字符
最大长度VARCHAR(n):最多 8,000 字符NVARCHAR(n):最多 4,000 字符

(3)N前缀的使用

当您需要处理非英文字符(如中文、日文、阿拉伯文等)或需要确保字符跨系统兼容时,必须使用 N前缀

假设有一个存储用户名的表:

CREATE TABLE Users ( Id INT IDENTITY PRIMARY KEY,    UserName NVARCHAR(50) -- 定义为 Unicode 列
);

情况一:错误写法(不使用 N):这里 '张三' 作为 VARCHAR 字符串处理,如果数据库代码页不支持中文,会导致乱码(如 ??)。

INSERT INTO Users (UserName) VALUES ('张三');

情况二:正确写法(使用 N

INSERT INTO Users (UserName) VALUES (N'张三');
-- 正确插入中文字符
INSERT INTO Users (UserName) VALUES (N'すばらしい');
-- 正确插入日文字符
INSERT INTO Users (UserName) VALUES (N'محمد');
-- 正确插入阿拉伯文字符

情况三:查询时的比较

-- 可能无法正确匹配
SELECT * FROM Users WHERE UserName = '张三';
​
-- 正确的 Unicode 字符串比较
SELECT * FROM Users WHERE UserName = N'张三';

(4)其他使用场景

A. 存储过程参数

CREATE PROCEDURE AddUser@Name NVARCHAR(50)
AS
BEGININSERT INTO Users (UserName) VALUES (@Name);
END
​
-- 调用时也需要使用 N 前缀
EXEC AddUser @Name = N'李四';

B. 函数参数

SELECT * FROM Users 
WHERE UserName LIKE N'张%'; -- 使用 Unicode 模式匹配

C. 变量声明

DECLARE @MyName NVARCHAR(50) = N'王五';
http://www.dtcms.com/a/354013.html

相关文章:

  • synchronized和Lock有什么区别?
  • Vue3》》基础
  • Ubuntu 20.04.6交叉编译得到Ubuntu 16.04.6的可执行文件
  • 5GNR CSI反馈 TypeI码本
  • Shader开发(十七)着色器中的纹理采样与渲染
  • OpenCV4.X库功能全解---个人笔记
  • 基于51单片机温度控制系统报警器恒温箱水温设计
  • Oh My Zsh + Tabby 终端配置指南
  • CB1-2-基础启航
  • 工业 DCS 全面科普:从入门到 AI 赋能的未来
  • 大视码垛机器人:以技术优势撬动工业码垛升级
  • 【datawhale组队学习】RAG技术 -TASK05 向量数据库实践(第三章3、4节)
  • Scala面试题及详细答案100道(21-30)-- 面向对象编程
  • 丝杆支撑座如何助力自动化设备精准定位?
  • 对接连连支付(四)-- 收款查询
  • 在Python中处理GDB、MDB和Shapefile文件转换
  • 滥用Mybatis一级缓存引发OOM问题
  • 如何使用asyncio库
  • 汽车电气系统的发展演进为测试带来了哪些影响?
  • LangChain4J-(3)-模型参数配置
  • AI生成音乐模型发展现状与前景
  • prettier、eslint、stylelint在项目中使用
  • 理解虚拟 DOM:前端开发中的高效渲染利器
  • Linux操作系统——TCP服务端并发模型
  • Java全栈开发面试实战:从基础到复杂场景的深度解析
  • 【51单片机】【protues仿真】基于51单片机点阵屏系统
  • 全域管控,一触可达:复合机器人远程监控方案重塑智能制造
  • Boosting(提升法)详解
  • Spring Boot + Dubbo 实战教程:打造高性能微服务架构
  • 深度学习12 Reinforcement Learning with Human Feedback