私のストアドプロシージャは、次のようになります。一度使用した後でCTEにアクセスできないのはなぜですか?
WITH MYCTE(....)
AS
(
...
)
UPDATE ... (using my CTE)
DELETE (using my CTE) <--- says the object, my CTE, doesn't exist
は、私は一度だけ、それを使用することはできますか?
私のストアドプロシージャは、次のようになります。一度使用した後でCTEにアクセスできないのはなぜですか?
WITH MYCTE(....)
AS
(
...
)
UPDATE ... (using my CTE)
DELETE (using my CTE) <--- says the object, my CTE, doesn't exist
は、私は一度だけ、それを使用することはできますか?
例のコードでは、CTEはUPDATEに対してのみ存続します。それをもっと長くする必要がある場合は、#tempTableまたは@tableVariableにそれを設定し、その中からUPDATEおよびDELETEを実行することを検討してください。
また、影響を受ける行をキャプチャできるように、次のようにOUTPUT句を使用するようにUPDATEを追加することもできます。そして、ここのように、DELETEでそれらを使用します。
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)
素晴らしい答え。私は何年もSQL Serverを使用してきましたが、OUTPUTを実行できるかどうかはわかりませんでした。それは間違いなく将来的に便利になるでしょう。 – WesleyJohnson
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
句は、その後、複数のクエリで使用するために永久的なオブジェクトを作成されていません。それだけであなたがその句を追加している1つのクエリを修正しています!非常に異なる機能が必要な場合は、代わりにビューを使用することを検討してください。
...またはテンポラリテーブル(#または@)。 –
CTEは、 '本当の' 何も作成しないでください。それらは単なる言語要素であり、ステートメント内で繰り返し使用できるテーブル式を表現する方法です。あなたは
WITH cteFoo AS (select ... from table where ...)
select ... from cteFoo where ...
は、CTEと派生テーブルは非常に似てい
select ... from (select ... from table where ....) as cteFoo where ...
、派生テーブルを使用して、任意のクエリはCTEとして書き直さすることができ、かつ任意の非再帰CTEができるというのがもうひとつの方法であると言うとき派生テーブルを使用してクエリとして書き直すことができます。個人的には、より簡潔で読みやすいように、CTEフォームをはるかに優先しています。
のCTEは、表の発現を可能にする一度だけ宣言するために複数回使用:
select ...
from (
select ... from table where ...) as a
join (
select ... from table where ...) as b
on ...
where ...
CTEは明らかに、より読みやすいです:
WITH cte AS (select ... from table where ...)
select ...
from cte a join cte b on ...
where ...
は、意味的に類似した派生テーブルの形でこれを比較してください。しかし、2つのフォームが同じクエリを生成していることを理解する必要があります。中間結果が作成され、中間結果に対して結合が実行されることをCTEフォームが示唆することがありますが、これは当てはまりません。 CTEフォームは、派生テーブルと全く同じ形式にコンパイルされます。これは、CTEのテーブル式がの2倍ので実行されていることを明確にしています。
これはT-SQLでセミコロンを使用する理由の良い例です。 UPDATE文とDELETE文の後に '; 'を正しく置くと、CTEがUPDATE文の_partであることが明確になります。 – NReilingh