我的存储过程如下所示:
WITH MYCTE(....)
AS
(
...
)
UPDATE ... (using my CTE)
DELETE ( using my CTE) <--- says the object, my CTE, doesn't exist
我只能使用一次吗?
我的存储过程如下所示:
WITH MYCTE(....)
AS
(
...
)
UPDATE ... (using my CTE)
DELETE ( using my CTE) <--- says the object, my CTE, doesn't exist
我只能使用一次吗?
在您的示例代码中,CTE 仅针对 UPDATE 持续存在。如果您需要它持续更长时间,请考虑使用它填充 #tempTable 或 @tableVariable,然后从中更新和删除。
You may also augment your UPDATE to use an OUTPUT clause, like the following, so you can capture the affected rows. And use them in the DELETE, like here:
set nocount on
DECLARE @Table table (PK int, col1 varchar(5))
DECLARE @SavedPks table (PK int)
INSERT INTO @Table VALUES (1,'g')
INSERT INTO @Table VALUES (2,'g')
INSERT INTO @Table VALUES (3,'g')
INSERT INTO @Table VALUES (4,'g')
INSERT INTO @Table VALUES (5,'x')
INSERT INTO @Table VALUES (6,'x')
set nocount off
;WITH MYCTE
AS
(
SELECT PK, col1 FROM @Table
)
UPDATE MYCTE
SET col1='xyz'
OUTPUT INSERTED.PK
INTO @SavedPks
WHERE col1='g'
SELECT 'A',* FROM @Table
DELETE @Table
WHERE PK IN (SELECT PK from @SavedPks)
SELECT 'B',* FROM @Table
OUTPUT:
(4 row(s) affected)
PK col1
---- ----------- -----
A 1 xyz
A 2 xyz
A 3 xyz
A 4 xyz
A 5 x
A 6 x
(6 row(s) affected)
(4 row(s) affected)
PK col1
---- ----------- -----
B 5 x
B 6 x
(2 row(s) affected)
CTE 表达式仅在其主体中有效。如果您想在其他地方使用它,您也应该重复该WITH
子句。
WITH MYCTE(....) AS ( ... )
UPDATE ... (using my CTE);
-- a semicolon is necessary for statements followed by a CTE declaration
WITH MYCTE(....) AS ( ... )
DELETE ( using my CTE);
是的,该WITH MYCTE
子句并没有创建一个永久对象以在之后的多个查询中使用:它只是修改您要添加该子句的一个查询!如果您需要非常不同的功能,请考虑使用视图...
CTE don't create anything 'real'. They are merely a language element, a way to express a table expression that will be used, possible repeatedly, in a statement. When you say
WITH cteFoo AS (select ... from table where ...)
select ... from cteFoo where ...
is just another way of saying
select ... from (select ... from table where ....) as cteFoo where ...
CTE and derived tables are very similar, any query using derived tables can be rewriten as a CTE, and any non-recursive CTE can be rewritten as a query using derived tables. Personally, I much more preffer the CTE form as is more concise and easy to read.
CTEs allow for a table expression used multiple times to be declare only once:
WITH cte AS (select ... from table where ...)
select ...
from cte a join cte b on ...
where ...
Compare this with the semantically similar derived table form:
select ...
from (
select ... from table where ...) as a
join (
select ... from table where ...) as b
on ...
where ...
The CTE is clearly more readable. But you must understand that the two forms are producing the same query. The CTE form might suggest that an intermediate result is created then the join is run on the intermediate result, but this is not true. The CTE form is compiled into exactly the same form as the derived table one, which makes clear the fact that the CTE's table expresion is run twice.