SQL Server にて 「このコンテキストではサブクエリは許可されません。スカラ式だけが許可されます。」というエラーが出力されましたので、検証してみました。
以前 SQL Server 2008 で作成したプロシージャのコンパイルが通らないのです。
エラーが出力された環境は SQL Server 2005 です。
現在、SQL Server 2016 Developer Edition が誰でもダウンロード可能になっており、その環境において再度検証してみたところ、普通にコンパイルが通ります。
前提条件
・Windows 7 professional 以降 / Windows Server 2008 R2 以降
・SQL Server 2005 Developer / Standard / Enterprise
1.用語について
サブクエリとはSELECT区の中のフィールドにSELECT区を記述して、その結果を値として取得すること
例えば、以下のようなSQLのことです。(赤字で示した部分です)
SELECT 1
,(SELECT [NAME] FROM T_Customer WHERE ID= 2)
FROM [dbo].[T_Customer]
WHERE ID = 2
SELECT 1
,[NAME]
FROM [dbo].[T_Customer]
WHERE [NAME] = (SELECT [NAME] FROM [dbo].[T_Customer] WHERE ID = 2)
※上記例はパフォーマンスやデータ定義的によろしくない例ですが、例えとしてはわかりやすい例だと思って記述しています。
次にスカラ式とは単一のデータとなる式の事です。つまりは、サブクエリの中のSELECT区が複数の行を返す場合、非スカラ式となります。単一のデータを返す場合をスカラ式サブクエリと呼びます。
2.対象となるサンプルSQL
エラーとなるプロシージャのサンプルSQLは以下の通りです。
USE testDB
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
DROP PROCEDURE IF EXISTS [dbo].[SubQueryTest]
GO
CREATE PROCEDURE [dbo].[SubQueryTest]
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[T_Customer]
([ID]
,[NAME]
) VALUES (
1
,(SELECT [NAME] FROM [dbo].[T_Customer] WHERE ID = 2)
);
END;
INSERT文のSELECT区の中にさらにSELECT区を記述(ネスト)すると、SQL Server 2005 ではコンパイルが通りません。この場合、T_CustomerテーブルはID列により一意のデータが取得できるはずですので、スカラ式となるはずです。
しかしながら、標題のとおりエラーとなります。SQL Server 2008 でも SQL Server 2016 でもコンパイルも実行も可能です。そこから推測するに、SQL Server 2005 でのみの不具合?または未定義機能であったのではないかと考えます。
3.補足
ただ、上記のSQL例では、パフォーマンスが良くありません。
INSERT INTO [dbo].[T_Customer]
([ID]
,[NAME]
)
SELECT 1
,[NAME]
FROM [dbo].[T_Customer]
WHERE ID = 2)
);
上記のようにすると良いと記述されているサイトがよく見受けられますが、それでは、複数件のINSERTができません。
例えば、設定値を取得して、同じ設定値を複数のIDに対してINSERTする場合は以下のように記述することがパフォーマンスを高めるSQLです。
--サブクエリではなく、予め設定値を取得しておく
DECLARE @SettingValue As INT;
SELECT @SettingValue = [Value]
FROM T_Settings
WHERE ID = 1
;
--取得した値の変数でINSERTする
INSERT INTO [dbo].[T_Customer]
([ID]
,[NAME]
,[Flg]
)
SELECT [ID]
,[NAME]
,@SettingValue
FROM [dbo].[T_Customer_BK]
;
しかしながら、業務で使用するSQLにはサブクエリで取得するほうがパフォーマンスが良い場合があります。そのような場合、SQL Sever 2005 では厳しいでしょうね。そもそも、SQL Server 2005 は2016年4月にサポートが終了していますので、新しいSQL Server に乗り換える必要がありますね。
最後までお読みいただき、ありがとうございます。
他にも SQL Server に関する記事をご紹介しておりますのでご参考頂ければ幸いです。
- 関連記事
-