我知道如何使用 .NET 完成我的任务,但我只想在 SQL 中完成。
我需要遍历主键有些随意的所有行。它可以是一个数字或一系列字母,也可能是任何数量的不寻常的东西。
我知道我可以做这样的事情......
DECLARE @numRows INT
SET @numRows = (SELECT COUNT(pkField) FROM myTable)<p></p>
<p>DECLARE @I INT
SET @I = 1
WHILE (@I <= @numRows)
BEGIN
--Do what I need to here
SET @I = @I + 1
END</p>
...如果我的行以连续的方式编入索引,但如果不是,我对 SQL 的了解还不够多。我不断遇到“游标”的使用,但我读到的关于避免使用游标的文章也同样多。
我找到了 this SO solution但我不确定这是否是我所需要的?
我很感激任何想法。
最佳答案
如果要遍历行,请使用游标。按照您所展示的方式进行操作效率要低得多。基本上你正在做的是一个游标而不使用 SQL Server 的游标工具。仅仅因为您不使用关键字 CURSOR 并不意味着它不是游标。从逻辑上讲,这就是你所拥有的。您的每个选择基本上都是对基础表的查询。特别是如果表没有索引,它的效率可能比游标低得多。您可以做一些事情来使游标不那么糟糕...FORWARD_ONLY,等等。有时制作静态游标会使事情变得更快,有时会使事情变慢。阅读 CURSOR 语句。
现实是为了避免游标,您不只是使用 select 语句发明游标,那是愚蠢的,应该解雇这样做的人。声称这不是游标的人是在自欺欺人……您需要重新考虑整个问题。有些事情没有游标是无法完成的,而对于那些,有游标。基本上我会将游标定义为在表上逐行执行操作的任何机制。
无论如何,您尝试做的事情缺少的部分是您可以通过创建映射表将非数字键转换为数字键:
SELECT IDENTITY(BIGINT, 1, 1) AS numKey, pkField INTO #keymap
FROM MyTable
DECLARE @I INT
SET @I = 1
WHILE (@I <= @numRows)
BEGIN
SELECT mt.*
FROM myTable mt inner join #keymap km on km.pkfield = mt.pkfield
WHERE numkey = @I
--Do what I need to here
SET @I = @I + 1
END
这仍然很糟糕,因为现在您正在对每条记录进行连接...可能稍微好一点:
A) 选择 IDENTITY(BIGINT, 1, 1) AS numKey, * INTO #keymap
来 self 的表格
现在#keymap 与您的原始表是同一张表,但带有数字键,因此您拥有的解决方案无需连接即可工作...但是如果表很大或者您想更新它,那么这不好
B) 而不是进行连接
SELECT IDENTITY(BIGINT, 1, 1) AS numKey, pkField INTO #keymap
FROM MyTable
DECLARE @I INT, @myKey VARCHAR(255) -- assume varchar
SET @I = 1
WHILE (@I <= @numRows)
BEGIN
SELECT @myKey = pkfield FROM #keymap WHERE numKey = @i
SELECT mt.*
FROM myTable
WHERE pkfield = @myKey
--Do what I need to here
SET @I = @I + 1
END
这样就不会有连接,但是你现在正在做两个查询......你甚至可能需要索引#keymap ....
最好的办法是重新评估您的问题。有时您可以使用 CASE WHEN 或标识列来避免游标。这真的取决于问题。但是对于那些需要使用游标的情况,使用实际的 CURSOR 通常比其他方法快得多。更快的是用 .NET、Java,甚至 Perl/Python 编写程序。我有一个 SQL Server 2000 函数,它使用两个嵌套游标,在我放弃之前花了一个多小时。当我编写一个 Perl 程序来做同样的事情时,它只花了 10 分钟。 Perl 与任何解释语言一样,比编译语言慢得多。 Java/C/C++/C# 可能会快 10/20/30 倍....所以如果你真的需要一个游标,最好用另一种编程语言来做。特别是如果您使用的是 SQL Server 2005,其中嵌入了 CLR(公共(public)语言运行时)...
关于sql - 使用 SQL 遍历非整数行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3018869/