[解決済み] スカラー変数を宣言する必要があります。
質問
ストアドプロシージャにこのSQLを書きましたが、うまくいきません。
declare @tableName varchar(max) = 'TblTest'
declare @col1Name varchar(max) = 'VALUE1'
declare @col2Name varchar(max) = 'VALUE2'
declare @value1 varchar(max)
declare @value2 varchar(200)
execute('Select TOP 1 @value1='+@col1Name+', @value2='+@col2Name+' From '+ @tableName +' Where ID = 61')
select @value1
execute('Select TOP 1 @value1=VALUE1, @value2=VALUE2 From TblTest Where ID = 61')
このSQLは、このエラーを投げます。
スカラー変数 "@value1"を宣言する必要があります。
SQLを動的に生成しているのですが、変数に値を取り込みたいのですが。どうすればいいでしょうか?
どのように解決するのですか?
が表示される原因は
DECLARE
のエラーは、動的なステートメントが別々のバッチで処理されるためで、これはスコープの問題に帰結します。 SQL Serverで利用できるスコープについては、もっと正式な定義があるのかもしれませんが、一般的には、可用性の高いものから順に、次の3つを覚えておけば十分だと思います。
グローバル :
サーバー全体で利用可能なオブジェクトで、ハッシュ/パウンド記号のダブルで作成される一時テーブルなど(
##GLOBALTABLE
のように呼びます)。 グローバルオブジェクトについては、SQL Serverであろうとなかろうと、他のアプリケーションと同じように非常に注意深くなければなりません。 私が本質的に言っているのは、このスコープに入らないようにするための注意点として、特に心に留めておいてほしいということです。
IF ( OBJECT_ID( 'tempdb.dbo.##GlobalTable' ) IS NULL )
BEGIN
CREATE TABLE ##GlobalTable
(
Val BIT
);
INSERT INTO ##GlobalTable ( Val )
VALUES ( 1 );
END;
GO
-- This table may now be accessed by any connection in any database,
-- assuming the caller has sufficient privileges to do so, of course.
セッション :
特定のspidに参照ロックされたオブジェクト。 私の頭の中では、セッションオブジェクトの唯一のタイプは、#Tableのように定義された通常の一時テーブルです。 セッションスコープにあるということは、本質的には、バッチ (
GO
が完了すると、このオブジェクトへの参照は正常に解決され続ける。
これらは
は
他のセッションから技術的にアクセス可能
しかし、tempdbでランダムな名前を取得し、それらにアクセスすることは、いずれにせよ少し面倒なので、プログラムでそうすることは、多少偉業でしょう。
-- Start of session;
-- Start of batch;
IF ( OBJECT_ID( 'tempdb.dbo.#t_Test' ) IS NULL )
BEGIN
CREATE TABLE #t_Test
(
Val BIT
);
INSERT INTO #t_Test ( Val )
VALUES ( 1 );
END;
GO
-- End of batch;
-- Start of batch;
SELECT *
FROM #t_Test;
GO
-- End of batch;
新しいセッション(別の spid を持つ接続)を開くと、上記の 2 番目のバッチは、そのセッションが
#t_Test
オブジェクト名です。
バッチ :
通常の変数、例えばあなたの
@value1
と
@value2
は、それらが宣言されたバッチに対してのみスコープされます。 とは異なり
#Temp
テーブルの場合、クエリブロックが
GO
これらの変数は、セッションで使用できなくなります。 これが、今回のエラーの原因となったスコープレベルです。
-- Start of session;
-- Start of batch;
DECLARE @test BIT = 1;
PRINT @test;
GO
-- End of batch;
-- Start of batch;
PRINT @Test; -- Msg 137, Level 15, State 2, Line 2
-- Must declare the scalar variable "@Test".
GO
-- End of batch;
なるほど、それで?
このダイナミックステートメントで何が起こっているかというと
EXECUTE()
コマンドは、実行したバッチを壊すことなく、事実上、別のバッチとして評価されます。
EXECUTE()
は良いものですが、しかし
sp_executesql()
私は前者を最も単純な場合にのみ使用します(明示的に、ステートメントにほとんど動的要素がない場合、主に、そうでない場合は使い勝手の悪いDDLを騙すために使用します)。
CREATE
ステートメントを他のバッチの途中で実行させることができます)。
AaronBertrandの
上記の回答は、動的なステートメントを評価する際にオプティマイザの機能を活用したもので、パフォーマンスも以下と同様となりますが、さらに発展させる価値があるのではないかと考えました。
@param
というのは、まあパラメータですね。
IF NOT EXISTS ( SELECT 1
FROM sys.objects
WHERE name = 'TblTest'
AND type = 'U' )
BEGIN
--DROP TABLE dbo.TblTest;
CREATE TABLE dbo.TblTest
(
ID INTEGER,
VALUE1 VARCHAR( 1 ),
VALUE2 VARCHAR( 1 )
);
INSERT INTO dbo.TblTest ( ID, VALUE1, VALUE2 )
VALUES ( 61, 'A', 'B' );
END;
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR( MAX ),
@PRM NVARCHAR( MAX ),
@value1 VARCHAR( MAX ),
@value2 VARCHAR( 200 ),
@Table VARCHAR( 32 ),
@ID INTEGER;
SET @Table = 'TblTest';
SET @ID = 61;
SET @PRM = '
@_ID INTEGER,
@_value1 VARCHAR( MAX ) OUT,
@_value2 VARCHAR( 200 ) OUT';
SET @SQL = '
SELECT @_value1 = VALUE1,
@_value2 = VALUE2
FROM dbo.[' + REPLACE( @Table, '''', '' ) + ']
WHERE ID = @_ID;';
EXECUTE dbo.sp_executesql @statement = @SQL, @param = @PRM,
@_ID = @ID, @_value1 = @value1 OUT, @_value2 = @value2 OUT;
PRINT @value1 + ' ' + @value2;
SET NOCOUNT OFF;
関連
-
[解決済み] TEXTIMAGE_ON [PRIMARY]とは何ですか?
-
[解決済み] sql文の角括弧[]の使い方を教えてください。
-
[解決済み] SSISの日付と時刻の連結
-
[解決済み] NVARCHAR(MAX)の最大文字数を教えてください。[重複しています]。
-
[解決済み] SQL Serverのタイムスタンプ列をdatetime形式に変換する方法
-
[解決済み] SQL Serverは、ビュークエリでLEFT JOINをLEFT OUTER JOINに置き換えます。
-
[解決済み] SQL ServerでGROUP BYと一緒にDISTINCTを使用する
-
[解決済み] SQL Server の DateTime データ型から日付だけを返す方法
-
[解決済み】SQL Server。クエリーは高速ですが、プロシージャから遅い
-
[解決済み] 変数としてのテーブル名
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 等値演算で "SQL_Latin1_General_CP1_CI_AS" と "Latin1_General_CI_AS" の照合の競合を解決できない
-
[解決済み] SQL Server: sys.master_files vs. sys.database_files
-
[解決済み] 階層テーブルの設計
-
[解決済み] データ損失の可能性があるため、スキーマの更新を終了します。
-
[解決済み] テーブルが存在しない場合、"Table 'dbo.Foo' already exists." というエラーはどのように解決すればよいですか?
-
[解決済み] テーブルの上位1レコードを更新する sql server [重複].
-
[解決済み] EF: テキストデータ型は比較できないため、DISTINCT として選択できません。
-
[解決済み] ミリタリータイムを使用するDatetimeフィールド - 標準時間のみが必要です。
-
[解決済み] create関数は、バッチ内の唯一のステートメントでなければなりません。
-
[解決済み] データベース内の全テーブルのサイズを取得する