FC2ブログ

記事一覧

このコンテキストではサブクエリは許可されません。スカラ式だけが許可されます。 | SQL Server


SQL Server にて 「このコンテキストではサブクエリは許可されません。スカラ式だけが許可されます。」というエラーが出力されましたので、検証してみました。

以前 SQL Server 2008 で作成したプロシージャのコンパイルが通らないのです。
エラーが出力された環境は SQL Server 2005 です。
現在、SQL Server 2016 Developer Edition が誰でもダウンロード可能になっており、その環境において再度検証してみたところ、普通にコンパイルが通ります。


SqlInsertSubQuery_01.png


前提条件
・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 に関する記事をご紹介しておりますのでご参考頂ければ幸いです。


関連記事

コメント

コメントの投稿

※名前とタイトルが入力されていないコメントでは他のコメントとの区別ができません。

 入力されていないコメントには返信しませんのであらかじめご了承くださいませ。

※ニックネームでも良いので必ずご入力ください。

    

※必ずご入力ください。

    
    

※必ずご入力ください。

※技術的な質問には環境やエラーについて正確かつ詳細にお教えください。

・正確なエラーの内容

・Windowsのバージョン番号

・Visual Studioのバージョン

・機器の型番

・アプリやソフトのバージョン

    

カテゴリ別記事一覧

広告

プロフィール

石河 純


著者名 :石河 純
自己紹介:素人上がりのIT技術者。趣味は卓球・車・ボウリング

IT関連の知識はざっくりとこんな感じです。
【OS関連】
WindowsServer: 2012/2008R2/2003/2000/NT4
Windows: 10/8/7/XP/2000/me/NT4/98
Linux: CentOS RedHatLinux9
Mac: macOS Sierra 10.12 / OSX Lion 10.7.5 / OSX Snow Leopard 10.6.8
【言語・データベース】
VB.net ASP.NET C#.net Java VBA
Xamarin.Forms
Oracle10g SQLServer2008R2 SQLAnywhere8/11/16
ActiveReport CrystalReport ReportNet(IBM)
【ネットワーク関連】
CCNP シスコ技術者認定
Cisco Catalyst シリーズ
Yamaha RTXシリーズ
FireWall関連
【WEB関連】
SEO SEM CSS IIS6/7 apache2

休みの日は卓球をやっています。
現在、卓球用品通販ショップは休業中です。