SQLビュー-変数はありませんか?


83

ビュー内で変数を宣言することは可能ですか?例えば:

Declare @SomeVar varchar(8) = 'something'

構文エラーが発生します:

キーワード「Declare」の近くの構文が正しくありません。

回答:


66

あなたは正しいです。ローカル変数はVIEWでは許可されていません。

テーブル値関数でローカル変数を設定できます。これにより、結果セットが返されます(ビューと同様)。

http://msdn.microsoft.com/en-us/library/ms191165.aspx

例えば

CREATE FUNCTION dbo.udf_foo()
RETURNS @ret TABLE (col INT)
AS
BEGIN
  DECLARE @myvar INT;
  SELECT @myvar = 1;
  INSERT INTO @ret SELECT @myvar;
  RETURN;
END;
GO
SELECT * FROM dbo.udf_foo();
GO

その効率はビューの効率と似ていますか?
RaRdEvA

いいえ、TVFはしばしば遅いです。「SQLServerのテーブル値関数(TVF)は良い考えのように見えますが、潜在的なパフォーマンスの問題のホストを覆い隠します。TVFは、実行計画の一部をシリアルのままにし(並列処理を回避します)、不正な行推定を生成します。また、マルチステートメントTVFは、利用可能な最善の最適化さえ得られない可能性があります。要するに、TVFは悪臭を放ちます。」brentozar.com/blitzcache/tvf-join
wp78de

49

WITHを使用して式を定義できます。次に、単純なサブ選択を実行して、これらの定義にアクセスします。

CREATE VIEW MyView
AS
  WITH MyVars (SomeVar, Var2)
  AS (
    SELECT
      'something' AS 'SomeVar',
      123 AS 'Var2'
  )

  SELECT *
  FROM MyTable
  WHERE x = (SELECT SomeVar FROM MyVars)

3
これは定数であり、変数ではありません!
ウラジスラフ

2
@Vladislavテーブルのデータを同じように簡単に使用(フィルタリング?)できます。
Dodecaphone

18

編集: @bummiが指摘したように、以前の回答でCTEを使用しようとしましたが、これは正しくありませんでした。このオプションは代わりに機能するはずです:

この問題を回避するために、CROSSAPPLYを使用する1つのオプションを次に示します。

SELECT st.Value, Constants.CONSTANT_ONE, Constants.CONSTANT_TWO
FROM SomeTable st
CROSS APPLY (
    SELECT 'Value1' AS CONSTANT_ONE,
           'Value2' AS CONSTANT_TWO
) Constants

訂正していただきありがとうございます-代わりにCROSSAPPLYを使用するように更新されました。
ダニエルニール

これは機能しますが、クロスアプライの列はすべての行に対して再初期化されませんか?特に、パフォーマンスが大幅に低下する計算値の場合。ローカル変数とCTEがビューで利用できないのは悲しいことですが、なぜだろうか?
t_D 2015年

1
@T_D「ビュー」で「CTE」を作成して使用できます。
Semuserable

6

@datenstationには正しい概念がありました。CTEを使用して変数の名前をキャッシュする実際の例を次に示します。

CREATE VIEW vwImportant_Users AS
WITH params AS (
    SELECT 
    varType='%Admin%', 
    varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers, params
    WHERE status > varMinStatus OR name LIKE varType

SELECT * FROM vwImportant_Users

また経由 JOIN

WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers INNER JOIN params ON 1=1
    WHERE status > varMinStatus OR name LIKE varType

また経由 CROSS APPLY

WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers CROSS APPLY params
    WHERE status > varMinStatus OR name LIKE varType

4

前述のspencer7593として関数を使用することは、動的データの正しいアプローチです。静的データの場合、SQLデータ設計と一貫性のあるよりパフォーマンスの高いアプローチ(sprocsで大量のプロシージャルコードを書き込むアンチパターンとは対照的に)は、静的値を使用して別のテーブルを作成し、それに結合することです。SQLエンジンはJOINを中心に効果的な実行プランを構築でき、必要に応じてインデックスを追加できる可能性があるため、これはパフォーマンスの観点から非常に有益です。

関数(またはインライン計算値)を使用することの欠点は、返される可能性のあるすべての行に対してコールアウトが発生することです。これにはコストがかかります。どうして?SQLは、最初に計算値を使用して完全なデータセットを作成してから、そのデータセットにWHERE句を適用する必要があるためです。

10回のうち9回は、クエリで動的に計算されたセル値を必要としないはずです。何が必要かを理解し、それをサポートするデータモデルを設計し、そのデータモデルに半動的データを入力し(たとえばバッチジョブを介して)、SQLエンジンを使用して標準SQLを介して手間のかかる作業を行う方がはるかに優れています。


3

はい、これは正しいです。ビューに変数を含めることはできません(他の制限もあります)。

ビューは、結果をselectステートメントで置き換えることができる場合に使用できます。


テーブル関数はselectステートメントで置き換えることができ、ローカル変数があります。
JeffO 2017年

selectステートメントはローカル変数を持つことができないので、ビューも持つことができないと言っていますか?
JeffO 2017年

1
@JeffO「ビューに変数を含めることはできません」と私は言いました。これは不明確ですか?
ホーガン

最後の文です。ビューはselectステートメントを置き換えることができますが、それは変数と何の関係がありますか?テーブル関数でselectステートメントを置き換えることはできませんが、変数を含めることはできますか?
JeffO 2017

1
テーブル関数はselectステートメントに置き換えることもできますが、テーブル関数は、結合など、ビューで使用できるすべての場所で使用できるわけではありません。彼が言おうとしているのは、ビューは単一のselectステートメントを置き換えることはできますが、複数のステートメントを置き換えることはできないということです。BEGINキーワードは、CREATEVIEWステートメントおよびインライン関数では無効です。マルチステートメントスクリプトを作成する必要があります。プロシージャまたは複数のステートメント関数は、おそらくこれを行うための最良の方法です。
Arlen Beiler 2017年

1

私がやっていることは、テーブル変数と同じ選択を実行するビューを作成し、そのビューを2番目のビューにリンクすることです。したがって、ビューは別のビューから選択できます。これは同じ結果を達成します


2
ベン、非常に小さなテーブルを扱っていない限り、これはパフォーマンスの問題を引き起こす可能性があります。
ロジクソロジスト2016

テーブルが非常に小さい(3レコード)場合でも、100万レコードのビューではパフォーマンスに大きな問題が発生します。
st_stefanov

0

どのくらいの頻度でビューを更新する必要がありますか?新しいデータが月に1回来るという同様のケースがあります。次に、それをロードする必要があり、ロードプロセス中に新しいテーブルを作成する必要があります。その瞬間、私は自分の見方を変えて変化を検討します。私はこの他の質問の情報をベースとして使用しました:

ビューを動的に作成する&同義語

そこでは、2つの方法でそれを行うことが提案されています。

  1. 同義語を使用します。
  2. 動的SQLを使用してビューを作成します(これが私の結果を達成するのに役立ちました)。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.