この構造でプロシージャを作成しましたが、datetime
入力パラメータでは機能しません
このクエリを実行しましたが、
declare @a datetime
declare @b datetime
set @a='2012/04/06 12:23:45'
set @b='2012/08/06 21:10:12'
exec LogProcedure 'AccountLog', N'test', @a, @b
しかし、SQL Serverはこのエラーを受け取った
文字列から日付や時刻を変換するときに変換に失敗しました。
しかし、このクエリでテストすると動作します
exec LogProcedure 'AccountLog',N'test'
ストアドプロシージャコード:
alter PROCEDURE LogProcedure
@TableName VARCHAR(60),
@SearchString NVARCHAR(50),
@DateFirst DateTime = '',
@DateLast DateTime = ''
AS
BEGIN
SET NOCOUNT ON
DECLARE @FinalSQL NVARCHAR(MAX)
SET @FINALSQL = 'SELECT * FROM [' + @TableName + '] where 1=2 '
IF @DateFirst <> '' and @DateLast <> ''
set @FinalSQL = @FinalSQL + ' or convert (Date,DateLog) >= '''+@DateFirst + ' and convert (Date,DateLog) <='''+@DateLast
SELECT
@FinalSQL = @FinalSQL + ' or [' + SYSCOLUMNS.NAME + '] LIKE N''%' + @SearchString + '%'' '
FROM SYSCOLUMNS
WHERE OBJECT_NAME(id) = @TableName
AND TYPE_NAME(SYSCOLUMNS.XTYPE) IN ('VARCHAR','NVARCHAR','CHAR','NCHAR','INT','DECIMAL')
ORDER BY COLID
EXEC(@FinalSQL)
END
このクエリも当てはまります
SELECT *
FROM AccountLog
where 1=2 or convert (Date, DateLog) >= '2012/04/06'
and convert (Date, DateLog) <='2012/08/06'
日付の文字列表現にはISO-8601形式を使用する必要があります。それ以外は、SQL Serverの言語と日付形式の設定に依存します。
日付のみを使用する場合のDATETIME
のISO-8601形式は、次のとおりです。YYYYMMDD
(ダッシュやアンティヒングなし!)
時間部分を含むDATETIME
の場合、YYYY-MM-DDTHH:MM:SS
(ダッシュと、日付部分と時間部分を分離するための中央にT
)があります。
SQL Server 2008以降で文字列をDATE
に変換する場合は、YYYY-MM-DD
(ダッシュ付き)を使用して同じ結果を得ることができます。そして、なぜこれが非常に一貫性がなく、混乱しているのかを聞かないでください。
だからあなたの場合、あなたは試してみてください:
declare @a datetime
declare @b datetime
set @a = '2012-04-06T12:23:45' -- 6th of April, 2012
set @b = '2012-08-06T21:10:12' -- 6th of August, 2012
exec LogProcedure 'AccountLog', N'test', @a, @b
さらに-ストアドプロシージャには問題があります。datetime
と文字列を連結して文字列にしているのに、最初にdatetime
を文字列に変換せず、閉じることも忘れているためです。両方の日付の後のステートメント内の引用符。
この行をここに変更してください:
IF @DateFirst <> '' and @DateLast <> ''
SET @FinalSQL = @FinalSQL + ' OR CONVERT(Date, DateLog) >= ''' +
CONVERT(VARCHAR(50), @DateFirst, 126) + -- convert @DateFirst to string for concatenation!
''' AND CONVERT(Date, DateLog) <=''' + -- you need closing quotes after @DateFirst!
CONVERT(VARCHAR(50), @DateLast, 126) + '''' -- convert @DateLast to string and also: closing tags after that missing!
これらの設定を使用して、現在問題を含んでいるストアドプロシージャを修正すると、動作します。
SPのこの部分で:
_IF @DateFirst <> '' and @DateLast <> ''
set @FinalSQL = @FinalSQL
+ ' or convert (Date,DateLog) >= ''' + @DateFirst
+ ' and convert (Date,DateLog) <=''' + @DateLast
_
文字列と日付時刻を連結しようとしています。
datetime
型はvarchar
/nvarchar
よりも優先度が高いため、_+
_演算子は、文字列と日時の間で発生すると、加算として解釈されます。連結としてではなく、エンジンは文字列部分(' or convert (Date,DateLog) >= '''
など)を日時または数値に変換しようとします。そして失敗します。
プロシージャを呼び出すときに最後の2つのパラメーターを省略すると、条件はfalseと評価され、問題のステートメントは実行されないため、これは発生しません。
状況を修正するには、日時変数の明示的なキャストを文字列に追加する必要があります。
_set @FinalSQL = @FinalSQL
+ ' or convert (Date,DateLog) >= ''' + convert(date, @DateFirst)
+ ' and convert (Date,DateLog) <=''' + convert(date, @DateLast)
_
また、閉じ一重引用符を追加する必要があります。
_set @FinalSQL = @FinalSQL
+ ' or convert (Date,DateLog) >= ''' + convert(date, @DateFirst) + ''''
+ ' and convert (Date,DateLog) <=''' + convert(date, @DateLast) + ''''
_