error40无法打开到sql_SQL-mysql游标与触发器

b37040e323929b3211ba84ce6d2282c8.png

一 前言

本篇内容是关于mysql游标和触发器的知识,学习本篇的基础是知识追寻者之前发过的文章(公众号读者看专辑)

《SQL-你真的了解什么SQL么?》

《SQL-小白最佳入门sql查询一》

《SQL-小白最佳入门sql查询二》

《SQL- 多年开发人员都不懂的插入与更新删除操作注意点》

《SQL-SQL事物操作》

《SQL-Mysql数据类型》

《SQL-mysql视图的前世今生》

《SQL-mysql储存过程》

公众号:知识追寻者

知识追寻者(Inheriting the spirit of open source, Spreading technology knowledge;)

二 游标

2.1 游标的概念

游标的本质就是查询后的结果集;当我们对查询的结果集进行前一行或者后一行类似的操作时就可以使用到游标

2.2 游标的语法

  • 首先需要 定义游标; declare 游标名称 cursor for 查询语句;
  • 其次,打开游标; open 游标名称
  • 然后,对查询的结果集 即游标进行 检索行至变量提供使用
  • 最后关闭游标; close 游标名称

2.3 使用游标

准备的表

CREATE TABLE `oder_detail` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `detail_name` varchar(255) DEFAULT NULL COMMENT '订单明细',
  `price` decimal(10,2) DEFAULT NULL COMMENT '价格',
  `oid` int(11) DEFAULT NULL COMMENT '订单id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='订单明细表';

准备的数据

INSERT INTO `zszxz`.`oder_detail`(`id`, `detail_name`, `price`, `oid`) VALUES (1, '毛巾', 20.00, 1);
INSERT INTO `zszxz`.`oder_detail`(`id`, `detail_name`, `price`, `oid`) VALUES (2, '牙膏', 15.00, 1);
INSERT INTO `zszxz`.`oder_detail`(`id`, `detail_name`, `price`, `oid`) VALUES (3, '杯子', 5.00, 1);
INSERT INTO `zszxz`.`oder_detail`(`id`, `detail_name`, `price`, `oid`) VALUES (4, '毛巾', 15.00, 2);
INSERT INTO `zszxz`.`oder_detail`(`id`, `detail_name`, `price`, `oid`) VALUES (5, '杯子', 15.00, 2);
​

简单的使用游标

查询oid为1 的订单明细名称 的结果集作为游标;

打开游标后抓取每行将结果赋值给变量name

CREATE PROCEDURE printName()
BEGIN
    -- 订单名称
    declare name varchar(20);
    -- 创建游标
    declare cur cursor for select detail_name from oder_detail where oid = '1';
    -- 打开游标
    open cur;
        fetch cur into name;
        select name;
    -- 关闭游标
    close cur;
END;

调用储存过程

call printName;

打印结果如下,只有一条数据,说明上述方式只在游标中抓取到一条数据,而且是表里面行号最小的行;

name
------
毛巾

在循环中使用游标

将 查询oid为1的 结果集赋值给游标;通过游标抓取每行 将 订单明细名称和价格分别赋值给变量 name 和 detail_price; 在 循环无法继续时 会出现 SQLSTATE '02000' ; 即此通过 变量 continue 时设置 done 为1 代表 true,此时循环结束,跳出循环;

drop procedure if exists  printDetail;
CREATE PROCEDURE printDetail()
BEGIN
    -- 订单名称
    declare name varchar(20);
        -- 价格
    declare detail_price decimal(8,2);
    -- 结束标志变量(默认为假)
    declare done boolean default 0;
    -- 创建游标
    declare cur cursor for select detail_name,price from oder_detail where oid = '1';
    -- 指定游标循环结束时的返回值
    declare continue HANDLER for SQLSTATE '02000' set done = 1;
    -- 打开游标
    open cur;
    -- 循环游标数据
    detail_loop:loop
            -- 根据游标当前指向的一条数据
            fetch cur into name,detail_price;
            select name , detail_price;
            -- 判断游标的循环是否结束
            if done then
                    -- 跳出游标循环
                    leave detail_loop;    
            end if;
        -- 结束游标循环
    end loop;
    -- 关闭游标
    close cur;
END;

调用储存过程

-- 调用存储过程
call printDetail();

美中不足的是会多遍历最后一行,如果要精细处理还是需要自定义标志位进行跳出循环;

三 触发器

3.1触发器的概念

触发器是指当表发生改变的时候触发的动作;听起来有点抽象,举个栗子,当你往表中插入数据的时候,此时表发生了改变,现在想要在每次插入数据之前检测所有的入参是否都是小写,此时就可以用触发器来检测;经过上面的分析知道使用一个基本的触发器,至少表要发生改变,还要满足一个被触发的事件;

表发生改变通常指 增删改,其动作可以发生在增删改 之前或者之后;触发事件就是我们需要写的储存过程;

  • update (after/ before)
  • insert (after/ before)
  • delete (after/ before)

3.2 触发器的基本语法

  • 创建触发器: create trigger 触发器名称 触发动作 on 表名 for each row [触发事件]
  • 删除触发器:drop trigger 触发器名称;
  • 查看触发器:show triggers;
tip : 触发器是依赖于表创建,没有表就没有触发器,比如视图,临时表都不是真实的表,它们是没有触发器;一般来说每个表都有触发器的限制,一般最多支持6个不同类型的触发器;由于使用触发器会频繁的改变表的每行,故其十分影响性能,特别对一些更新频率比较快的大表,如果设置触发器就非常占用系统资源;一般来说触发器用在表变动较小的小表, 不使用触发器就立即删除;

3.3 insert 触发器示例

创建触发器; 创建一个触发器 getPrice 作用于 oder_detail 表的每行,每当 插入数据之后就查询这条订单明细的价格赋值给变量 @price ;小伙伴可能会疑惑 NEW 是何物,其是一张虚表,记录者被插入数据的行;故我们能在NEW表中获取每次插入的数据;

-- insert 触发器
CREATE TRIGGER getPrice AFTER INSERT ON oder_detail FOR EACH ROW
SELECT NEW.price INTO @price;

检测插入触发器; 插入一条数据,使用查询语句查询变量 显示为 20;

-- 检测插入触发器
​
INSERT INTO `oder_detail`( `detail_name`, `price`, `oid`) VALUES ( '脸盆', 20.00, 2);
​
select @price;

删除触发器;

-- 删除触发器
drop trigger getPrice;

3.4 update 触发器示例

将插入后触发器改为更新后的触发器如下 , 只需要改动 after insert 为 after update 即可;

CREATE TRIGGER getPrice AFTER update ON oder_detail FOR EACH ROW
SELECT NEW.price INTO @price;

将之前的插入的SQL语句进行修改价格,并查询价格,此时价格为30;NEW虚表储存的是即将更新的数据;

UPDATE `oder_detail` SET `price` = 30.00 WHERE `id` = 6;
​
select @price;

删除触发器

-- 删除触发器
drop trigger getPrice;

将 更新触发器的NEW表改为OLD表

CREATE TRIGGER getPrice AFTER update ON oder_detail FOR EACH ROW
SELECT OLD.price INTO @price;

更新价格为40

UPDATE `oder_detail` SET `price` = 40.00 WHERE `id` = 6;

此时查询 价格为30,说明OLD表触发的是原始数据值;

select @price;
tip : 更新触发器主要是要搞懂OLD存放原始数据,NEW存放即将更新的数据;NEW表可以设置更改值,二OLD表是只读;

3.5 delete 触发器

将 更新触发器改为 delete 触发器, 之前我们省略了 begin, end 如果是多条执行语句则需要加上;

CREATE TRIGGER getPrice AFTER delete ON oder_detail FOR EACH ROW
begin 
SELECT OLD.price INTO @price;
end;

删除之前的SQL数据

delete from oder_detail where `id` = 6;

查询价格为40,OLD表存放的是将要被删除的数据;

select @price;
<think>好的,我现在需要回答用户的问题:“T-SQL语句标准SQL语句的区别”。用户还提供了几个站内引用,我需要结合这些引用来组织答案。首先,我得回忆一下T-SQL标准SQL的基本概念,然后对比它们的差异。 首先,标准SQL是结构化查询语言的国际标准,由ANSIISO制定,主要用于关系数据库的管理操作。而T-SQL是微软在SQL Server中扩展的版本,增加了更多功能特性。用户提供的引用中有几个例子,比如触发器中的@@ROWCOUNT、存储过程、事务控制等,这些都属于T-SQL特有的功能。 接下来,我需要从几个方面来对比两者的区别: 1. **功能扩展**:T-SQL有更多编程结构,如变量、流程控制(IF...ELSE、WHILE)、错误处理(TRY...CATCH)。例如引用[1]中的触发器使用了RAISERROR,引用中的异常处理模块用了TRY...CATCH,这些都是标准SQL没有的。 2. **内置函数变量**:T-SQL有像@@IDENTITY、@@ROWCOUNT这样的全局变量,如引用[1]提到的在触发器中获取插入记录的编号。标准SQL可能没有这些特定变量。 3. **存储过程触发器**:T-SQL支持复杂的存储过程触发器,引用[1]中的INSTEAD OF触发器就是例子,而标准SQL触发器功能较为基础。 4. **事务并发控制**:T-SQL提供了更多的事务控制选项,比如显式事务(BEGIN TRANSACTION)锁提示,如用户之前回答中的WITH (UPDLOCK)。引用[3]中的分离附加数据库操作也涉及T-SQL特定的系统存储过程。 5. **特定语法命令**:比如T-SQL的EXEC命令执行存储过程,而标准SQL可能使用CALL。还有像引用[4]中的外键定义,虽然标准SQL也有,但某些语法细节可能不同,比如自增列的写法(AUTO_INCREMENT vs IDENTITY)。 6. **数据库管理**:T-SQL包含许多SQL Server特有的管理命令,如引用[3]中的sp_detach_dbsp_executesql,这些在标准SQL中不存在。 需要确保回答结构清晰,分点说明,并引用用户提供的资料来支持论点。同,用户可能对实际应用场景感兴趣,比如在开发中何选择T-SQL,或者迁移数据的注意事项。最后,生成相关问题要围绕T-SQL特性、迁移问题、性能优化等方向。</think>### T-SQL标准SQL的核心区别 T-SQL(Transact-SQL)是微软SQL Server的扩展SQL实现,在兼容标准SQL(ANSI/ISO SQL)的基础上,增加了**编程增强、特有函数数据库管理功能**。以下是主要差异点: --- #### 一、编程能力扩展 1. **流程控制语句** T-SQL支持过程化编程: - `IF...ELSE` 条件分支 - `WHILE` 循环 - `TRY...CATCH` 异常处理(如用户事务代码中的错误回滚逻辑[^1]) ```sql BEGIN TRY -- 可能出错的代码 END TRY BEGIN CATCH PRINT ERROR_MESSAGE() -- 输出错误信息 END CATCH ``` 2. **变量系统函数** - 声明局部变量:`DECLARE @var INT` - 使用全局变量:`@@ROWCOUNT`(获取操作影响行数)[^1]、`@@IDENTITY`(获取插入的标识值) - 示例:引用[1]中触发器通过`IF UPDATE(name)`检测字段修改 --- #### 二、数据库对象增强 1. **存储过程触发器** - T-SQL支持复杂业务逻辑封装: ```sql CREATE PROCEDURE GetStudentCount AS BEGIN SELECT COUNT(*) FROM students END ``` - 触发器类型扩展(如`INSTEAD OF`触发器[^1]) 2. **扩展DDL操作** - 数据库分离/附加:`EXEC sp_detach_db`[^3] - 动态SQL执行:`EXEC sp_executesql`(引用[3]中杀死进程的游标操作) --- #### 三、事务并发控制 1. **显式事务管理** - `BEGIN TRANSACTION`、`COMMIT`、`ROLLBACK`(如用户设计的事务提交逻辑[^1]) - 表级锁提示(`WITH (UPDLOCK)`) 2. **隔离级别定制** ```sql SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ``` --- #### 四、特有语法差异 | **功能** | **标准SQL** | **T-SQL** | |------------------|-----------------------|-----------------------------| | 自增列 | `AUTO_INCREMENT` | `IDENTITY(1,1)`[^4] | | 字符串拼接 | `CONCAT()` | `+` 运算符 | | 执行存储过程 | `CALL proc_name()` | `EXEC proc_name` | --- #### 五、应用场景对比 - **标准SQL**:跨数据库兼容场景(如MySQL、PostgreSQL迁移) - **T-SQL**:SQL Server深度集成需求(如: - 使用游标处理逐行操作(引用[3]的进程终止逻辑) - 复杂业务规则通过触发器实现[^1] - 高性能事务处理(银行系统) --- ### 总结 T-SQL在标准SQL基础上增加了**过程化编程能力****SQL Server专属功能**,适合需要深度数据库集成的场景,而标准SQL更注重跨平台兼容性[^1][^3][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值