2

以下に、動的にしようとしているストアドプロシージャのコードスニペットを示します。つまり、を実行しEXEC('select * from table_name WHERE filter=something')て結果セットをWebサービスに返します。クエリしているテーブルのweek_start_dateフィールドは、日付フィールドではなく、日時フィールドです。クエリで正しく解釈されるように、datetimeパラメーターを動的SQLに適切に追加するにはどうすればよいですか?また、コードをよりクリーンにする方法について提案があれば、アドバイスを差し上げます。

データを見ると、次のような値があります。

2012-08-10 00:00:00.000

動作していないT-SQLコード:

ALTER PROCEDURE [dbo].[logged_time_by_week]
    @week_start_date_filter datetime = null
AS
BEGIN

...。

    DECLARE @select_clause nvarchar(4000);
    DECLARE @from_clause nvarchar(4000);
    DECLARE @where_clause nvarchar(4000);
    DECLARE @order_clause nvarchar(4000);

    SET @select_clause = 
        ' SELECT '
        + ' [sunday_hours],'
        + ' [monday_hours],'
        + ' [tuesday_hours],'
        + ' [wednesday_hours],'
        + ' [thursday_hours],'
        + ' [friday_hours],'
        + ' [saturday_hours]'

    SET @from_clause =
        ' FROM '
        + ' [timesheet_row] '

    SET @where_clause = ''

    IF @week_start_date_filter IS NOT NULL AND @week_start_date_filter != ''
    BEGIN 
        IF @where_clause != ''
        BEGIN
            SET @where_clause = @where_clause + ' AND ' 
        END
        SET @where_clause = @where_clause + ' [week_start_date] = ' + CONVERT(nvarchar, @week_start_date_filter)
    END

    IF @where_clause != '' 
    BEGIN
        SET @where_clause = ' WHERE ' + @where_clause
    END

    SET @order_clause = ' ORDER BY [' + @sort_column + '] ' + @sort_direction

    EXEC(@select_clause + @from_clause + @where_clause + @order_clause)
4

3 に答える 3

3

これらの種類のエラーをトラブルシューティングする最も簡単な方法は、生成されたSQLを出力して、失敗する理由を確認することです。

クエリを見るだけで、@week_start_date_filter変数の前後の引用符を修正する必要があると思います。

declare @week_start_date_filter datetime = getdate();
print ' [week_start_date] = ''' + CONVERT(nvarchar, @week_start_date_filter) + '''';

また、補足として、動的SQLを使用する必要がある場合は、代わりにパラメーター化されたSQLを使用することをお勧めします。テーブルのスキーマがわからないため、sys.objectsを使用した例を次に示します。

DECLARE
    @week_start_date_filter datetime    = (SELECT TOP(1) [create_date] FROM sys.objects),
    @sort_column            sysname     = N'create_date',
    @sort_direction         nvarchar(3) = N'ASC';


    DECLARE @select_clause nvarchar(4000);
    DECLARE @from_clause nvarchar(4000);
    DECLARE @where_clause nvarchar(4000);
    DECLARE @order_clause nvarchar(4000);

    SET @select_clause = 
        ' SELECT TOP(1) '
        + ' *';

    SET @from_clause =
        ' FROM '
        + ' sys.objects'

    SET @where_clause = ''

    IF @week_start_date_filter IS NOT NULL AND @week_start_date_filter != ''
    BEGIN 
        IF @where_clause != ''
        BEGIN
            SET @where_clause = @where_clause + ' AND ' 
        END
        SET @where_clause = @where_clause + ' [create_date] = @date_filter'
    END

    IF @where_clause != '' 
    BEGIN
        SET @where_clause = ' WHERE ' + @where_clause
    END

    SET @order_clause = ' ORDER BY [' + @sort_column + '] ' + @sort_direction

    DECLARE
        @SQL    nvarchar(max) = @select_clause + @from_clause + @where_clause + @order_clause,
        @Params nvarchar(200) = N'@date_filter datetime';


    EXEC sp_executesql
        @stmt        = @SQL,
        @params      = @Params,
        @date_filter = @week_start_date_filter;
于 2012-10-09T17:56:16.667 に答える
3

これはあなたを正しい道に導くはずです、私は思います:

declare @dtValue datetime = '2012-10-02 15:34:53'
declare @CRLF    char(2)  = char(0x0D) + char(0x0A)
declare @QT1     char(1)  = ''''
declare @dtFrom  datetime      = convert(date,@dtValue,112)
declare @dtThru  datetime      = dateadd(ms,-3,dateadd(day,1,@dtFrom))
declare @sql     varchar(8000)

select @sql = 'select *'            + @CRLF
            + 'from sys.objects so' + @CRLF
            + 'where so.create_date between '
            + quotename( convert(varchar,@dtFrom,126) , @QT1 )
            + ' and '
            + quotename( convert(varchar,@dtThru,126) , @QT1 )

select sqlCommand = @sql

exec ( @sql )

上記のコードはこのSQLを生成します:

select *
from sys.objects so
where so.create_date between '2012-10-02T00:00:00' and '2012-10-02T23:59:59.997'

奇妙な上限は、SQL Serverの奇妙な時間の概念によるもので、1分の最後の「ティック」は997ミリ秒であり、それより大きいミリ秒の値は次の分に切り上げられます(つまり、2012年10月2日23:59:59.999実際には2012年10月3日00:00:00.000)です。

于 2012-10-09T18:14:34.233 に答える
2

これはwhere句で機能するはずです。

SET @where_clause = @where_clause + 
' [week_start_date] = CONVERT(datetime, ' + @week_start_date_filter + ')'

また、week_start_date列が日時タイプでない場合は、上記のように変換する必要もあります。

于 2012-10-09T18:20:06.123 に答える