我是一个初学者问题。
这是一段有效的代码:
declare @RowNr int = 1
declare @CA int = 0
While @RowNr <= 1000
BEGIN
With CCWithRow AS
(
SELECT CA ,ROW_NUMBER() OVER (order by CA) as RowNr
FROM myCATable
)
SELECT @CA = CA, @RowNr = RowNr
FROM CCWithRow
WHERE RowNr = @RowNr
Set @RowNr += 1
--Doing something with @CA here
END
此代码不会:
declare @RowNr int = 1
declare @CA int = 0
With CCWithRow AS
(
SELECT CA ,ROW_NUMBER() OVER (order by CA) as RowNr
FROM myCATable
)
While @RowNr <= 1000
BEGIN
SELECT @CA = CA, @RowNr = RowNr
FROM CCWithRow
WHERE RowNr = @RowNr
Set @RowNr += 1
--Doing something with @CA here
END
问题:为什么我必须在循环内“定义”WITH?
我知道有更好的方法来解决原始问题,因此不应该成为主题。只是想知道,为什么我不能在循环之外定义WITH并在里面使用它。
答案 0 :(得分:2)
公用表表达式(CTE)可以被认为是临时表 在单个的执行范围内定义的结果集 SELECT,INSERT,UPDATE,DELETE或CREATE VIEW语句。
因此,公共表表达式用法必须在CTE定义结束后立即始终,因为它不在其他任何地方引用的范围内。这种情况也不例外。
答案 1 :(得分:1)
这是CTE的实施:
CTE只能由语句立即引用 遵循CTE 。这意味着如果你想使用CTE,你必须这样做 在CTE之后立即写入引用CTE的查询 T-SQL批处理。 (ref)
CTE的结果不是创建的对象,它只是一组基于CTE表达式解析的结果,非常类似于(select ..)
子查询,类似于您无法在其他地方访问。
答案 2 :(得分:1)
检查MSDN Common Table Expressions
上的以下声明可以将公用表表达式(CTE)视为已定义的临时结果集within the execution scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement.
它不会作为对象存储,只会持续一段时间 查询。在前面的select语句之后立即释放它 到CTE表达。
查看Microsoft Magazine文章的部分 - Structure of a CTE,了解有关CTE的更多信息。
CTE是一种语言级构造 - 意味着SQL Server没有 在内部创建临时或虚拟表。 CTE的基础查询 每次在紧接着的时候引用它时都会被调用 查询。