クエリ文字列の変数を宣言する


92

MS SQL Server 2005でこれを行う方法があるかどうか疑問に思っていました。

  DECLARE @theDate varchar(60)
  SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

  SELECT    AdministratorCode, 
            SUM(Total) as theTotal, 
            SUM(WOD.Quantity) as theQty, 
            AVG(Total) as avgTotal, 
            (SELECT SUM(tblWOD.Amount)
                FROM tblWOD
                JOIN tblWO on tblWOD.OrderID = tblWO.ID
                WHERE tblWO.Approved = '1' 
                AND tblWO.AdministratorCode = tblWO.AdministratorCode
                AND tblWO.OrderDate BETWEEN @theDate
            )
 ... etc

これは可能ですか?


回答:


96

可能ですが、動的SQLを使用する必要があります。続行する前に、動的SQLの呪いと祝福を
読むことをお勧めします ...

DECLARE @theDate varchar(60)
SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

DECLARE @SQL VARCHAR(MAX)  
SET @SQL = 'SELECT AdministratorCode, 
                   SUM(Total) as theTotal, 
                   SUM(WOD.Quantity) as theQty, 
                   AVG(Total) as avgTotal, 
                  (SELECT SUM(tblWOD.Amount)
                     FROM tblWOD
                     JOIN tblWO on tblWOD.OrderID = tblWO.ID
                    WHERE tblWO.Approved = ''1''
                      AND tblWO.AdministratorCode = tblWO.AdministratorCode
                      AND tblWO.OrderDate BETWEEN '+ @theDate +')'

EXEC(@SQL)

ダイナミックSQLは、実行前に文字列として構成される単なるSQLステートメントです。したがって、通常の文字列連結が発生します。動的SQLは、SQL構文で許可されていない次のようなことを行う場合は常に必要です。

  • IN句の値のコンマ区切りリストを表す単一のパラメーター
  • 値とSQL構文の両方を表す変数(IE:指定した例)

EXEC sp_executesql bind / preparedstatementパラメータを使用できるので、SQLインジェクション攻撃のために一重引用符などをエスケープすることについて心配する必要はありません。


これが最も正解だと思います。最近もSQL Server 2005を使用していますが、OPのように変数をクエリ文字列の置換に使用することはできません(構文エラーが生成されます)。@Poniesが言うように、変数に構文とデータ型の両方を含めることはできません。動的SQLは、文字列を介してSQL Serverでクエリを作成する方法です。あなたの引用とタイプに注意することを忘れないでください!実行する文字列では、datetimeやintなどのいくつかの型を変換または文字列連結のためにキャストする必要があります。
RoboBear

52
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

次に、このロジックを使用するようにクエリを変更します。

AND 
(
    tblWO.OrderDate > DATEADD(MILLISECOND, -1, @theDate) 
    AND tblWO.OrderDate < DATEADD(DAY, 1, @theDate)
)

2
待って。質問が2つの異なる日付を明確に示している場合、それは答えにはなりません。最後に@StealthRTでそれをどのようにコーディングしましたか?回答の「2010-08-31」の日付はどこにありますか?また、質問では、DECLARE変数を使用してコードを別のSELECTステートメントに置き換えることができるかどうかを明確に尋ねます。正しい答えは以下の通りです。
Fandango68

2

EXECの使用

次の例を使用して、SQLステートメントを作成できます。

DECLARE @sqlCommand varchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = '''London'''
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = ' + @city
EXEC (@sqlCommand)

sp_executesqlの使用

このアプローチを使用すると、クエリに渡されるデータ値が正しいデータ型であり、より多くの引用符を使用しないようにすることができます。

DECLARE @sqlCommand nvarchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = 'London'
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = @city'
EXECUTE sp_executesql @sqlCommand, N'@city nvarchar(75)', @city = @city

参照


1

最高評価の回答「動的SQLの呪いと祝福」にリンクされている記事で、著者は動的SQLを使用しないことが回答であると述べています。これを確認するには、ほぼ最後までスクロールします。

記事から:「正しい方法は、リストをユーザー定義関数またはストアドプロシージャを含むテーブルにアンパックすることです。」

もちろん、リストがテーブルに入ると、結合を使用できます。最高評価の回答に直接コメントできなかったので、このコメントを追加しました。


これは質問に対する答えを提供しません。十分な評判られると、どの投稿にもコメントできるようになります。代わりに、質問者からの説明を必要としない回答を提供してください。- レビューより
Sam M

サムありがとう Erland Sommarskogの提案を実装したら、コメントを詳細に更新します。また、彼はその答えを評価するに値するので、名前で彼を参照します。
DavidG、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.