CTE 执行多次
CTE executed multiple times
我今天在 SQL Server 2016 上遇到了 CTE 运行ning 的问题,目前我使用 table 变量解决了它,但是我不确定行为是否如此是错的还是我读错了文档。
当你运行这个查询时:
with cte(id) as
(
select NEWID() as id
)
select * from cte
union all
select * from cte
我希望相同的 guid 是两倍,但是有 2 个不同的 guid。根据文档 (https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver15),它 "Specifies a temporary named result set"。然而,上面的例子表明,它不是一个结果集,而是在使用时执行。
这个帖子不是要寻找不同的方法,而是要检查它是否有问题。
常见的 table 表达式不是临时的 table、物化视图或缓存的结果集。它们只是表达式,可以多次计算(这意味着对于像 NEWID()
这样的函数,每次计算表达式时都会得到一个新值)。我在 this post:
的“小心糖”部分谈到了这一点
Even in very simple cases, you can see that a CTE that accesses a table once, but is referenced multiple times, ends up evaluating the CTE (and hence accessing the underlying table) multiple times.
并在此处解决类似问题:
Martin Smith 在这里有一个深刻而透彻的回答:
- Which are more performant, CTE or temporary tables?
我确实理解许多人对 CTE 的工作方式做出假设,我很欣赏缓存 CTE 所提供的价值。这不是他们今天的工作方式,但您可以投票 this feedback item 来塑造未来的功能。
您也可以 ask for clarification in the official documentation - 但通常文档不会列出功能不能做的所有事情。一个常见的例子是,“为什么文档没有明确说明没有 ORDER BY
的 SELECT * FROM table
不能保证以某种特定顺序输出?”或者,更抽象地说,“为什么我的车的车主手册没有告诉我这辆车不能飞?”
与此同时,如果每次引用它的来源时都希望 NEWID()
具有相同的值,则应使用#temp table、@table 变量,或本地@variable。在您的示例中,更改可能很简单:
declare @newid uniqueidentifier = NEWID();
with cte(id) as
(
select @newid as id
)
select * from cte
union all
select * from cte
示例:db<>fiddle
我今天在 SQL Server 2016 上遇到了 CTE 运行ning 的问题,目前我使用 table 变量解决了它,但是我不确定行为是否如此是错的还是我读错了文档。
当你运行这个查询时:
with cte(id) as
(
select NEWID() as id
)
select * from cte
union all
select * from cte
我希望相同的 guid 是两倍,但是有 2 个不同的 guid。根据文档 (https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver15),它 "Specifies a temporary named result set"。然而,上面的例子表明,它不是一个结果集,而是在使用时执行。
这个帖子不是要寻找不同的方法,而是要检查它是否有问题。
常见的 table 表达式不是临时的 table、物化视图或缓存的结果集。它们只是表达式,可以多次计算(这意味着对于像 NEWID()
这样的函数,每次计算表达式时都会得到一个新值)。我在 this post:
Even in very simple cases, you can see that a CTE that accesses a table once, but is referenced multiple times, ends up evaluating the CTE (and hence accessing the underlying table) multiple times.
并在此处解决类似问题:
Martin Smith 在这里有一个深刻而透彻的回答:
- Which are more performant, CTE or temporary tables?
我确实理解许多人对 CTE 的工作方式做出假设,我很欣赏缓存 CTE 所提供的价值。这不是他们今天的工作方式,但您可以投票 this feedback item 来塑造未来的功能。
您也可以 ask for clarification in the official documentation - 但通常文档不会列出功能不能做的所有事情。一个常见的例子是,“为什么文档没有明确说明没有 ORDER BY
的 SELECT * FROM table
不能保证以某种特定顺序输出?”或者,更抽象地说,“为什么我的车的车主手册没有告诉我这辆车不能飞?”
与此同时,如果每次引用它的来源时都希望 NEWID()
具有相同的值,则应使用#temp table、@table 变量,或本地@variable。在您的示例中,更改可能很简单:
declare @newid uniqueidentifier = NEWID();
with cte(id) as
(
select @newid as id
)
select * from cte
union all
select * from cte
示例:db<>fiddle