web-dev-qa-db-ja.com

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

私は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

これは可能ですか?

80
StealthRT

可能ですが、動的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インジェクション攻撃のために一重引用符などをエスケープする必要はありません。

83
OMG Ponies
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

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

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

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

参考

2
Somnath Muluk

私は、トップクラスの回答にリンクされた記事の中で指摘します 動的SQLの呪いと祝福 著者は、回答は動的SQLを使用しないことであると述べています。これを見るためにほとんど終わりまでスクロールして下さい。

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

もちろん、リストがテーブルに入ったら、結合を使用できます。トップクラスの回答に直接コメントできなかったので、このコメントを追加しました。

1
DavidG