SQL Server EXISTS構造の利用方法
4539 ワード
EXISTS構造はTSQL関数で、カッコ内のサブクエリに対してブール変数を返します.サブクエリが任意のローを返すと、この構造は真を返します.そうでなければ、偽に戻ります.この構造は、クエリ・テーブルにレコードがあるかどうかに特に適しています.また、テーブルで更新を実行するか、文を挿入するかどうかを決定するのに適しています(この記事では、後で説明します).
Listing Aにテーブルが作成され、いくつかのデータが挿入されます.これにより、EXISTS構造がどのように動作しているかを見ることができます.Listing Bのスクリプトは、EXISTS構造を使用してSalesHistoryテーブルで各ローをチェックし、既存のローに基づいて変数を取得します.このスクリプトは1(真)を返します.これは、SalesHistoryテーブルにクエリーするローが含まれていることを意味します.
この場合、SalesHistoryテーブルにレコードが見つかった場合、EXISTS構造は検索を継続せず、すぐに1を返します.EXISTS構造を使用すると、条件を満たすレコードが見つかったらすぐに戻るという追加の利点があります.
Listing Cは上記のスクリプトと似ていますが、EXISTS条件が満たされていないため、戻り値は0です.
EXISTS構造の動作原理により,次の文で実現する機能は同じである.
SELECT * FROM SalesHistory
WHERE EXISTS(SELECT NULL)
SELECT * FROM SalesHistory
WHERE 1 = 1
SELECT * FROM SalesHistory
WHERE EXISTS(SELECT 1)
さっきのスクリプトでは、次の文に戸惑うかもしれません.
SELECT * FROM SalesHistory
WHERE EXISTS(SELECT NULL)
NULLはデータベース内の値(未知の値)であるため、NULL値が表示された場所でEXISTS構造は真を返します.
開発者はEXISTSを用いてサブクエリを操作することは少ない.次のクエリは、構造が異なるにもかかわらず、同じ結果セットを返します.1番目のクエリはEXISTSの関連サブクエリを使用し、2番目のクエリはSalesHistoryテーブルでSalePriceフィールドをそのフィールドの合計平均値と比較します.
SELECT * FROM SalesHistory sh
WHERE EXISTS
(
SELECT AVG(SalePrice)
FROM SalesHistory shi
HAVING AVG(SalePrice) > sh.SalePrice
)
SELECT * FROM SalesHistory sh
WHERE SalePrice <
(
SELECT AVG(SalePrice)
FROM SalesHistory shi
)
EXISTS操作を使用して、次の例のように、UPDATEまたはINSERT文を個別のレコードに使用するかどうかを決定できます.
IF EXISTS
(
SELECT * FROM SalesHistory
WHERE SaleDate = '1/1/2001' AND
Product = 'Computer' AND
SalePrice = 1000
)
UPDATE TOP(1) SalesHistory
SET SalePrice = 1100
WHERE SaleDate = '1/1/2001' AND
Product = 'Computer' AND
SalePrice = 1000
ELSE
INSERT INTO SalesHistory
(Product, SaleDate, SalePrice)
VALUES
('Computer', '1/1/2001', 1100)
実際の環境では、ここで説明した例は使用されないかもしれませんが、EXISTS構造を使用してどのDMLタイプを使用するかを決定する方法を示しています.
チャンスを与える
次回、クエリー文を書くときは、EXISTS構造を使うことを覚えておいてください.それは把握しやすくて、使うのも便利で、しかもプログラムの中であなたに多くの便利さを提供することができます.リストA
Listing Aにテーブルが作成され、いくつかのデータが挿入されます.これにより、EXISTS構造がどのように動作しているかを見ることができます.Listing Bのスクリプトは、EXISTS構造を使用してSalesHistoryテーブルで各ローをチェックし、既存のローに基づいて変数を取得します.このスクリプトは1(真)を返します.これは、SalesHistoryテーブルにクエリーするローが含まれていることを意味します.
この場合、SalesHistoryテーブルにレコードが見つかった場合、EXISTS構造は検索を継続せず、すぐに1を返します.EXISTS構造を使用すると、条件を満たすレコードが見つかったらすぐに戻るという追加の利点があります.
Listing Cは上記のスクリプトと似ていますが、EXISTS条件が満たされていないため、戻り値は0です.
EXISTS構造の動作原理により,次の文で実現する機能は同じである.
SELECT * FROM SalesHistory
WHERE EXISTS(SELECT NULL)
SELECT * FROM SalesHistory
WHERE 1 = 1
SELECT * FROM SalesHistory
WHERE EXISTS(SELECT 1)
さっきのスクリプトでは、次の文に戸惑うかもしれません.
SELECT * FROM SalesHistory
WHERE EXISTS(SELECT NULL)
NULLはデータベース内の値(未知の値)であるため、NULL値が表示された場所でEXISTS構造は真を返します.
開発者はEXISTSを用いてサブクエリを操作することは少ない.次のクエリは、構造が異なるにもかかわらず、同じ結果セットを返します.1番目のクエリはEXISTSの関連サブクエリを使用し、2番目のクエリはSalesHistoryテーブルでSalePriceフィールドをそのフィールドの合計平均値と比較します.
SELECT * FROM SalesHistory sh
WHERE EXISTS
(
SELECT AVG(SalePrice)
FROM SalesHistory shi
HAVING AVG(SalePrice) > sh.SalePrice
)
SELECT * FROM SalesHistory sh
WHERE SalePrice <
(
SELECT AVG(SalePrice)
FROM SalesHistory shi
)
EXISTS操作を使用して、次の例のように、UPDATEまたはINSERT文を個別のレコードに使用するかどうかを決定できます.
IF EXISTS
(
SELECT * FROM SalesHistory
WHERE SaleDate = '1/1/2001' AND
Product = 'Computer' AND
SalePrice = 1000
)
UPDATE TOP(1) SalesHistory
SET SalePrice = 1100
WHERE SaleDate = '1/1/2001' AND
Product = 'Computer' AND
SalePrice = 1000
ELSE
INSERT INTO SalesHistory
(Product, SaleDate, SalePrice)
VALUES
('Computer', '1/1/2001', 1100)
実際の環境では、ここで説明した例は使用されないかもしれませんが、EXISTS構造を使用してどのDMLタイプを使用するかを決定する方法を示しています.
チャンスを与える
次回、クエリー文を書くときは、EXISTS構造を使うことを覚えておいてください.それは把握しやすくて、使うのも便利で、しかもプログラムの中であなたに多くの便利さを提供することができます.リストA
IF OBJECT_ID('SalesHistory','U')>0
DROP TABLE SalesHistory
GO
CREATE TABLE SalesHistory
(
SaleID INT IDENTITY(1,1),
Product VARCHAR(30),
SaleDate DATETIME,
SalePrice MONEY
)
DECLARE @i SMALLINT
SET @i = 1
WHILE (@i <= 100)
BEGIN
INSERT INTO SalesHistory
(Product, SaleDate, SalePrice)
VALUES
('Computer', DATEADD(mm, @i, '3/10/2006'), DATEPART(ms, GETDATE()) + (@i + 57) )
INSERT INTO SalesHistory
(Product, SaleDate, SalePrice)
VALUES
('BigScreen', DATEADD(mm, @i, '3/2/2006'), DATEPART(ms, GETDATE()) + (@i + 13) )
INSERT INTO SalesHistory
(Product, SaleDate, SalePrice)
VALUES ('PoolTable', DATEADD(mm, @i, '2/11/2007'), DATEPART(ms, GETDATE()) + (@i + 29) )
SET @i = @i + 1
END
GO
×××××××××××××××××××××××××××××××××××××××××××
B
DECLARE @TablePopulated BIT
SET @TablePopulated = CASE WHEN EXISTS(SELECT * FROM SalesHistory) THEN 1 ELSE 0 END
SELECT @TablePopulated
×××××××××××××××××××××××××××××××××××××××××××××××××
C
DECLARE @TablePopulated BIT
SET @TablePopulated = CASE WHEN EXISTS(SELECT * FROM SalesHistory WHERE Product = 'Chair') THEN 1 ELSE 0 END
SELECT @TablePopulated