web-dev-qa-db-ja.com

プロシージャの入力パラメーターに日時を入力します

この構造でプロシージャを作成しましたが、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'
13
Salah Sanjabian

日付の文字列表現には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!

これらの設定を使用して、現在問題を含んでいるストアドプロシージャを修正すると、動作します。

27
marc_s

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) + ''''_
1
Andriy M