17

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'
4

2 に答える 2

35

日付の文字列表現には ISO-8601 形式を使用する必要があります。それ以外は、SQL Server の言語と日付形式の設定に依存します。

DATETIME日付のみを使用する場合 の a の ISO-8601 形式は次YYYYMMDDのとおりです。

DATETIME時間部分のa の場合は、YYYY-MM-DDTHH:MM:SS(ダッシュがあり、T日付と時刻の部分を区切るために真ん中に a があります)。

DATE文字列をSQL Server 2008 以降の に変換する場合は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!

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

于 2012-04-08T09:21:57.237 に答える
1

SP のこの部分:

IF @DateFirst <> '' and @DateLast <> ''
   set @FinalSQL  = @FinalSQL
       + '  or convert (Date,DateLog) >=     ''' + @DateFirst
       + ' and convert (Date,DateLog) <=''' + @DateLast  

文字列と日時を連結しようとしています。

型は/datetimeよりも優先度が高いため、演算子が文字列と日時の間で発生した場合、連結としてではなく加算として解釈され、エンジンは文字列部分 (およびその他) を日時または数値に変換しようとします。 . そして失敗します。varcharnvarchar+' or convert (Date,DateLog) >= '''

プロシージャを呼び出すときに最後の 2 つのパラメーターを省略した場合、条件が false と評価され、問題のあるステートメントが実行されないため、これは発生しません。

状況を修正するには、datetime 変数の明示的なキャストを文字列に追加する必要があります。

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) + ''''
于 2012-04-08T09:28:10.343 に答える