游标sql server

SQL Server cursors are one common topic on the Internet. You’ll find different opinions when to use them and when not to do it. Today, we’ll also talk about them and answer the question when (not) to use them.

SQL Server游标是Internet上的一个常见主题。 在何时使用它们以及何时不使用它们时,您会发现不同的意见。 今天,我们还将讨论它们,并回答何时(不)使用它们的问题。

数据模型和总体思路 (The Data Model and the general idea )

In the previous article, Intro to SQL Server loops, we talked about SQL Server loops, but we haven’t used data from the database. That was odd, but that should become much clearer now. Today, while explaining cursors, we’ll use the data from the database to show when (not) to use cursors. The data model we’ll be using is the same one we’re using throughout this series.

在上一篇文章“ SQL Server循环简介”中 ,我们讨论了SQL Server循环,但尚未使用数据库中的数据。 这很奇怪,但是现在应该变得更加清楚了。 今天,在解释游标时,我们将使用数据库中的数据来显示何时(不使用)游标。 在本系列中,我们将使用的数据模型与我们使用的数据模型相同。

SQL Server supports 3 different implementations of cursors – Transact-SQL cursors, API cursors, and Client cursors. In this article, we’ll focus on Transact-SQL cursors. You’ll easily recognize them because they are based on the DECLARE CURSOR syntax.

SQL Server支持3种不同的游标实现– Transact-SQL游标,API游标和客户端游标。 在本文中,我们将重点介绍Transact-SQL游标。 您会很容易识别它们,因为它们基于DECLARE CURSOR语法。

SQL Server游标–简介 (SQL Server Cursor – Introduction)

Before we move to code and examples, we should explain what SQL Server cursors are.

在转到代码和示例之前,我们应该解释什么是SQL Server游标。

The SQL Server cursor is T-SQL logic, which allows us to loop through the related query result. This enables us to take the actions sequentially – e.g., perform an update on a single row.

SQL Server游标是T-SQL逻辑,它使我们可以循环浏览相关的查询结果。 这使我们能够按顺序执行操作-例如,在一行上执行更新。

Sometimes this could (seem to) be helpful, but when working with databases, you shouldn’t use procedural programming patterns but rather stick to declarative programming. One of the main reasons is that DBMSs are already optimized to perform actions on sets of data, and therefore you shouldn’t be the one who’s trying to be “smarter than the system”.

有时这可能(似乎)很有帮助,但是在使用数据库时,您不应使用过程编程模式,而应坚持声明式编程。 主要原因之一是DBMS已经过优化,可以对数据集执行操作,因此,您不应成为试图“比系统更智能”的人。

Still, it’s good to know how they work. If nothing else, maybe you’ll meet them in the code you inherit, and you’ll have to rewrite the logic. And before doing anything, you should understand how it works.

尽管如此,还是很高兴知道它们是如何工作的。 如果没有别的,也许您会在继承的代码中遇到它们,并且必须重写逻辑。 在做任何事情之前,您应该了解它是如何工作的。

So, in case you need cursors, this is what you should know about them:

因此,如果您需要游标,那么这是您应该了解的内容:

  • Cursors use variables to store values returned in each part of the loop. Therefore, you’ll need to DECLARE all variables you’ll need 游标使用变量存储循环的每个部分中返回的值。 因此,您需要对所有需要的变量进行DECLARE
  • The next thing to do is to DECLARE … CURSOR FOR SELECT query, where you’ll declare a cursor and also define the query related to (populating) that cursor 下一步是DECLARE…CURSOR FOR SELECT查询,您将在其中声明一个游标并定义与(填充)该游标有关的查询
  • You’ll OPEN the cursor and FETCH NEXT from the cursor 您将打开光标并从光标处获取下一个
  • In the WHILE loop you’ll test the @@FETCH_STATUS variable (WHILE @@FETCH_STATUS = 0). If the condition holds, you’ll enter the loop BEGIN … END block and perform statements inside that block 在WHILE循环中,您将测试@@ FETCH_STATUS变量(WHILE @@ FETCH_STATUS = 0)。 如果条件成立,您将进入循环BEGIN…END块并在该块内执行语句
  • After you’ve looped through the whole result set, you’ll exit from the loop. You should CLOSE the cursor and DEALLOCATE it. Deallocating is important because this shall delete the cursor definition and free the memory used 遍历整个结果集之后,您将退出循环。 您应该关闭光标并取消分配它。 取消分配很重要,因为这将删除游标定义并释放所使用的内存

SQL Server游标–示例 (SQL Server Cursor – Examples)

Let’s now take a look at two cursor examples. While they are pretty simple, they nicely explain how cursors work.

现在,让我们看两个光标示例。 尽管它们非常简单,但它们很好地解释了游标的工作方式。

In the first example, we want to get all cities ids and names, together with their related country names. We’ll use the PRINT command to print combinations in each pass of the loop.

在第一个示例中,我们要获取所有城市的ID和名称以及相关的国家名称。 我们将使用PRINT命令在循环的每一遍中打印组合。

-- declare variables used in cursor
DECLARE @city_name VARCHAR(128);
DECLARE @country_name VARCHAR(128);
DECLARE @city_id INT;-- declare cursor
DECLARE cursor_city_country CURSOR FORSELECT city.id, TRIM(city.city_name), TRIM(country.country_name)FROM cityINNER JOIN country ON city.country_id = country.id;-- open cursor
OPEN cursor_city_country;-- loop through a cursor
FETCH NEXT FROM cursor_city_country INTO @city_id, @city_name, @country_name;
WHILE @@FETCH_STATUS = 0BEGINPRINT CONCAT('city id: ', @city_id, ' / city name: ', @city_name, ' / country name: ', @country_name);FETCH NEXT FROM cursor_city_country INTO @city_id, @city_name, @country_name;END;-- close and deallocate cursor
CLOSE cursor_city_country;
DEALLOCATE cursor_city_country;

Using the SQL Server cursor and the while loop returned exactly what we’ve expected – ids and names of all cities, and related countries, we have in the database.

使用SQL Server游标和while循环,可以准确返回我们期望的结果–数据库中所有城市以及相关国家/地区的ID和名称。

The most important thing to mention here is that we could simply return this result set using the original SQL query stored in the DECLARE part of the cursor, so there was no need for a cursor.

这里要提到的最重要的事情是,我们可以使用存储在游标的DECLARE部分中的原始SQL查询简单地返回此结果集,因此不需要游标。

We’ll go with one more example. This time we’ll query the information schema database to return the first 5 tables ordered by table name. While there’s not much sense in using such a query, this example shows you:

我们再举一个例子。 这次,我们将查询信息模式数据库以返回按表名排序的前5个表。 尽管使用这样的查询没有多大意义,但本示例向您展示:

  • query the information schema database 查询信息模式数据库
  • How to combine a few commands/statements we’ve mentioned in previous articles (IF … ELSE, WHILE loop, CONCAT) 如何结合我们在之前的文章中提到的一些命令/语句(IF…ELSE,WHILE循环,CONCAT)
-- declare variables used in cursor
DECLARE @table_name VARCHAR(128);
DECLARE @table_names_5 VARCHAR(128);-- declare cursor
DECLARE cursor_table_names CURSOR FORSELECT TOP 5 TABLE_NAME FROM INFORMATION_SCHEMA.TABLESORDER BY TABLE_NAME ASC;SET @table_names_5 = 'first 5 tables are: '
-- open cursor
OPEN cursor_table_names;-- loop through a cursor
FETCH NEXT FROM cursor_table_names INTO @table_name;
WHILE @@FETCH_STATUS = 0BEGINIF @table_names_5 = 'first 5 tables are: 'SET @table_names_5 = CONCAT(@table_names_5, @table_name)ELSESET @table_names_5 = CONCAT(@table_names_5, ', ', @table_name);     FETCH NEXT FROM cursor_table_names INTO @table_name;END;
PRINT @table_names_5;-- close and deallocate the cursor
CLOSE cursor_table_names;
DEALLOCATE cursor_table_names;

From the coding side, I would like to emphasize that this time, we haven’t printed anything in a loop but rather created a string using CONCAT. Also, we’ve used the IF statement to test if we’re in the first pass, and if so, we haven’t added “,”. Otherwise, we would add “,” to the string.

从编码方面,我想强调一下,这次,我们没有在循环中打印任何内容,而是使用CONCAT创建了一个字符串。 另外,我们已经使用IF语句来测试我们是否处于第一次通过状态,如果是,则没有添加“,”。 否则,我们将在字符串中添加“,”。

After the loop, we’ve printed the result string, closed and deallocated the cursor.

循环之后,我们打印了结果字符串,关闭并重新分配了游标。

We could achieve this using the STRING_AGG function. This one is available starting from the SQL Server 2017 and is the equivalent of MySQL GROUP_CONCAT function.

我们可以使用STRING_AGG函数来实现。 从SQL Server 2017开始提供此功能,等效于MySQL GROUP_CONCAT函数。

SQL Server游标–何时(不)使用它们? (SQL Server Cursor – When (Not) to use them?)

I’ll try to give an objective answer to the question – “When you should use SQL Server cursors and when not”? Since things change during the time and improvements shall be made, either on cursors, either on other objects that “replace” them, take into consideration the date when this article was written. So, let’ start.

我将尝试客观回答这个问题–“什么时候应该使用SQL Server游标,什么时候不使用”? 由于在此期间情况会发生变化,因此应在游标上或在“替换”它们的其他对象上进行改进,请考虑到撰写本文的日期。 所以,让我们开始吧。

You shouldn’t use cursors:

不应该使用游标

  • Intro to SQL Server loops, we’ve used loops, but not to loop through data. SQL Server循环简介”中 ,我们使用了循环,但没有遍历数据。

You could use cursors:

可以使用游标

  • Mostly for database administration tasks like backups, integrity checks, rebuilding indexes 主要用于数据库管理任务,例如备份,完整性检查,重建索引
  • For one-time tasks when you’re sure that possible poor performance won’t impact the overall system performance 对于一次性任务,当您确定可能的不良性能不会影响整体系统性能时
  • Calling a stored procedure a few times using different parameters. In that case, you would get parameters from cursor variables and make calls inside the loop

    使用不同的参数几次调用存储过程 。 在这种情况下,您将从游标变量中获取参数并在循环内进行调用

    Calling a stored procedure or another query inside the cursor (or loop) impacts performance a lot, because, in each step of the cursor loop, you’ll run the query/procedure from the start. If you decide to do that, you should be aware of possible consequences.

    在游标(或循环)内部调用存储过程或其他查询会极大地影响性能,因为在游标循环的每个步骤中,将从头开始运行查询/过程。 如果您决定这样做,则应注意可能的后果。

  • The previous hint brings us to the last bullet when you should use cursors. If you’re completely aware of how they work and you’re pretty sure it won’t impact performance, go for it 上一个提示将我们带到了您应该使用游标时的最后一个项目符号。 如果您完全了解它们的工作原理,并且确定它不会影响性能,那么请继续努力

SQL Server游标–为什么人们(不)使用它们? (SQL Server Cursor – Why people (don’t) use them?)

The last question I would like to answer is: Why would anyone use a cursor? This is how I see it:

我要回答的最后一个问题是:为什么有人会使用光标? 这是我的看法:

  • People who’re using them for one-time jobs or regular actions where they won’t impact performance have the excuse. One of the reasons is that such code is procedural code, and if you’re used to it, it’s very readable 将其用于不会影响绩效的一次性工作或定期行动的人会成为借口。 原因之一是这样的代码是过程代码,如果您习惯了它,那么它很可读
  • On the other hand, those who started learning about databases, and are used to procedural programming might use cursors because, as mentioned, they are much closer to procedural programming than to databases. This is not a reason to use them, because the only excuse here would be that you simply don’t know the other (right) way how to get things done 另一方面,那些开始学习数据库并习惯于过程编程的人可能会使用游标,因为如上所述,它们更接近过程编程而不是数据库。 这不是使用它们的原因,因为这里的唯一借口是您根本不知道另一种(正确的)方法来完成任务
  • The most important thing about cursors is that they are slow when compared to SQL statements, and therefore you should avoid using them because they will sooner or later lead to performance issues (unless you know exactly what you’re doing and why)
  • 关于游标,最重要的是,与SQL语句相比,游标速度较慢 ,因此应避免使用它们,因为游标迟早会导致性能问题(除非您确切地知道自己在做什么以及为什么)

I find it useful that you understand the concept of cursors because there is a great chance, you’ll meet them along the way. They were popular before some new options were added to SQL Server. Also, there is a chance you’ll continue working on a system where somebody before you used them, and you’ll have to continue where they stopped. Maybe you’ll need to replace the cursor (procedural code) with SQL (declarative code).

我发现了解游标的概念很有用,因为很有可能会遇到它们。 在将一些新选项添加​​到SQL Server之前,它们很流行。 同样,您有机会在使用某个人之前继续在一个系统上工作,而您必须在他们停止的地方继续工作。 也许您需要将游标(过程代码)替换为SQL(声明性代码)。

结论 (Conclusion)

There is no better conclusion on cursors, than – don’t use them

游标sql server_学习SQL:SQL Server游标相关推荐

  1. SQL语句学习之SQL基础的表创建以及添加数据

    SQL语句学习之SQL基础的表创建以及添加数据 学习目标1: 一周内掌握SQL基础语句 tip:主要是在牛客网(牛客网)上进行练习,里面有在线编程,可以直接运行,而且有解题的思路,比较清晰,而且容易了 ...

  2. SQL 知识点学习汇总,SQL学习这一篇就足够了

    SQL学习知识点汇总 1.SQL是什么? SQL其实是一种编程语言,用于访问和处理数据库的计算机语言 编程语言都有几个特性,有数据类型.可以做运算. 编程语言是为了编程而发明,而程序=数据+算法.所以 ...

  3. mysql 触发器 sql server_喜忧参半的SQL Server触发器

    SQL Server触发器在非常有争议的主题.它们能以较低的成本提供便利,但经常被开发人员.DBA误用,导致性能瓶颈或维护性挑战. 本文简要回顾了触发器,并深入讨论了如何有效地使用触发器,以及何时触发 ...

  4. mysql 8 sql server_终于将 SQL Server 成功迁移至 MySQL8.0 啦!!!

    之前一直使用 SQL Server 作为主数据库而不是 MySQL ,原因之一是单机 SQL Server 性能比 MySQL 强很多,另一个原因是之前客户的系统管理员大多只有 SQL Server ...

  5. Mybatis学习-动态SQL

    Mybatis学习-动态SQL Mybatis学习-动态SQL Mybatis学习-动态SQL 什么是动态SQL 搭建环境 IF 接口 Mapper 测试 trim (where, set) wher ...

  6. SQL Server基础操作(此随笔仅作为本人学习进度记录九!--游标)

    游标就是存储结果集,将从指定表中查询出符合条件的记录,组成了结果集,然后把它存到游标当中,如果要显示游标中的哪一条记录游标(游动的标识) !!!!非常重要的知识点,比较难理解!!!游标提供了对表中的数 ...

  7. mysql 临时表 事务_MySQL学习笔记十:游标/动态SQL/临时表/事务

    逆天十三少 发表于:2020-11-12 08:12 阅读: 90次 这篇教程主要讲解了MySQL学习笔记十:游标/动态SQL/临时表/事务,并附有相关的代码样列,我觉得非常有帮助,现在分享出来大家一 ...

  8. 游标sql server_SQL Server游标教程

    游标sql server 介绍 (Introduction) 大多数使用Microsoft SQL Server的人至少会听说过游标,而且即使人们基本了解SQL Server游标的作用,他们也不总是确 ...

  9. 游标sql server_SQL Server游标性能问题

    游标sql server 介绍 (Introduction) 在上一篇文章中,我们讨论了如何设置基本游标. 我们解释了游标是基于行的操作,它采用给定的SELECT语句并将数据处理分解为循环执行. 没有 ...

最新文章

  1. Geant4采用make和cmake编译运行geant4自带例子的方法
  2. mysql文件头标记_通过文件头准确识别PHP上传的文件类型 ( 一 )
  3. linux下查看服务器性能,linux命令查看服务器性能
  4. 从表达式到函数:表面的简洁
  5. python random包含尾部吗_你真的了解Python的random模块吗?
  6. Struts2请求处理的内部流程说明(版本二)
  7. PAT乙类1005之继续(3n+1)猜想 (25 分)
  8. 表格存储 SQL 查询多元索引
  9. Java基础入门笔记-算术运算符
  10. html pdf文档的格式控制符,关于Unicode控制字符RLO,LRO,PDF 的坑
  11. 安博中程研讨会-HTML5引领2012技术热潮
  12. 52 - 算法 - LeetCode 21 数据结构链表 头插法 递归
  13. PS 2022,PR 2018,AE 2017【百度网盘链接,没套路】
  14. html站点地图怎么做,如何制作网站地图,制作网站地图的步骤
  15. 网络安全等级保护制度介绍
  16. 中兴新支点操作系统_中兴新支点操作系统v3.2.2 最新版
  17. HDU 4699 Editor(双向链表)
  18. makefile通配符
  19. 知识星球,贡献C版本,OpenSSL,GMSSL,JS版本相关国密
  20. python怎么解矩阵方程_基于python解线性矩阵方程(numpy中的matrix类)

热门文章

  1. [220207] Find the Difference
  2. python 全部缩进一行_Python开发工具:缩进规则的使用
  3. Zabbix 配置钉钉脚本告警(4)
  4. PhotoshopCS5中将单位修改成百分比
  5. spring-boot-2.0.3之quartz集成,数据源问题,源码探究
  6. 基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题...
  7. 基于visual Studio2013解决C语言竞赛题之0608水仙花函数
  8. SilverLight:布局(3)StackPanel 对象
  9. mysql客户端登陆提示client option 'secure_auth' enabled错误
  10. HTTPS协议的简述