Я не могу разрешить Msg 241, уровень 16, состояние 1, строка 26 Ошибка преобразования при преобразовании даты и / или времени из строки символов - PullRequest
0 голосов
/ 02 августа 2020

Мне нужно было научиться отображать запрос в сводной таблице. Мне удалось решить все проблемы, кроме одной. При вводе действительных дат запрос выполняется правильно. Но мне нужно, чтобы запрос был динамическим c, но передавал даты через переменную в строку. Я включил как рабочий запрос, так и тот, который представляет проблему. Я пробовал все или доступные варианты, которые мог найти по ранее заданным вопросам, но безрезультатно.

Рабочий запрос

DECLARE @ColumnNames NVARCHAR(MAX) = ''
    DECLARE @sql NVARCHAR (MAX) = ''
    DECLARE @startdate as datetime = '2020-07-19 00:00:00'
    DECLARE @enddate as datetime = '2020-07-25 00:00:00'

    ;

    WITH DateRange(DateData) AS 
    (
    SELECT @startdate as Date
    UNION ALL
    SELECT DATEADD(d,1,DateData)
    FROM DateRange 
    WHERE DateData < @enddate
    )
    SELECT @ColumnNames += QUOTENAME(CONVERT(varchar(10),DateData,101)) +','
    FROM DateRange
    OPTION (MAXRECURSION 0)

    SET @ColumnNames = LEFT(@ColumnNames,LEN(@ColumnNames)-1)----------removes final comma

    SET @sql =

    'SELECT * FROM
 
    (SELECT TOP (100) PERCENT 
    CONVERT(varchar(10),dbo.TimePunche.DateWorked,101) AS DateWorked, 
                      dbo.Employee.LastName + '', '' + dbo.Employee.FirstName + '': '' + dbo.Employee.Login AS     Employee, 
                  SUM(dbo.TimeInOut.HoursWorked) AS Hours
                 FROM dbo.TimeInOut 
           INNER JOIN dbo.TimePunche ON dbo.TimeInOut.TimepuncheID = dbo.TimePunche.ID 
           INNER JOIN dbo.Location 
           INNER JOIN dbo.Employee ON dbo.Location.ID = dbo.Employee.LocationID ON dbo.TimePunche.EmployeeID = dbo.Employee.ID 
           INNER JOIN dbo.JobDescriptions ON dbo.TimeInOut.JobDescriptionID = dbo.JobDescriptions.ID 
           INNER JOIN dbo.LocationJobDescriptions ON dbo.Location.ID = dbo.LocationJobDescriptions.LocationID 
                  AND dbo.JobDescriptions.ID = dbo.LocationJobDescriptions.JobDescriptionID

               WHERE (dbo.Location.Name = N''PFG-City of Industry'') 
                 AND (dbo.TimePunche.DateWorked >= ''7-19-2020'') 
                 AND (dbo.TimePunche.DateWorked <= ''7-25-2020'') 
                 AND (dbo.JobDescriptions.JobDescription = ''House Keeping/Sanitation'') 
                  OR (dbo.Location.Name = N''PFG-City of Industry'') 
                 AND (dbo.TimePunche.DateWorked >= ''7-19-2020'')  
                 AND (dbo.TimePunche.DateWorked <= ''7-25-2020'') 
                 AND (dbo.JobDescriptions.JobDescription = ''Guard Shack'')
            
            GROUP BY 
            CONVERT(varchar(10), dbo.TimePunche.DateWorked, 101), 
                                 dbo.Employee.LastName + '', '' + dbo.Employee.FirstName + '': '' + dbo.Employee.Login) AS BaseData'

    EXECUTE sp_executesql @sql

Запрос, представляющий проблему

 DECLARE @ColumnNames NVARCHAR(MAX) = ''
    DECLARE @sql NVARCHAR (MAX) = ''
    DECLARE @startdate as datetime = '2020-07-19 00:00:00'
    DECLARE @enddate as datetime = '2020-07-25 00:00:00'

    ;

    WITH DateRange(DateData) AS 
    (
    SELECT @startdate as Date
    UNION ALL
    SELECT DATEADD(d,1,DateData)
    FROM DateRange 
    WHERE DateData < @enddate
    )
    SELECT @ColumnNames += QUOTENAME(CONVERT(varchar(10),DateData,101)) +','
    FROM DateRange
    OPTION (MAXRECURSION 0)

    SET @ColumnNames = LEFT(@ColumnNames,LEN(@ColumnNames)-1)----------removes final comma

    SET @sql =

    'SELECT * FROM
 
    (SELECT TOP (100) PERCENT 
    CONVERT(varchar(10),dbo.TimePunche.DateWorked,101) AS DateWorked, 
                      dbo.Employee.LastName + '', '' + dbo.Employee.FirstName + '': '' + dbo.Employee.Login AS     Employee, 
                  SUM(dbo.TimeInOut.HoursWorked) AS Hours
                 FROM dbo.TimeInOut 
           INNER JOIN dbo.TimePunche ON dbo.TimeInOut.TimepuncheID = dbo.TimePunche.ID 
           INNER JOIN dbo.Location 
           INNER JOIN dbo.Employee ON dbo.Location.ID = dbo.Employee.LocationID ON dbo.TimePunche.EmployeeID = dbo.Employee.ID 
           INNER JOIN dbo.JobDescriptions ON dbo.TimeInOut.JobDescriptionID = dbo.JobDescriptions.ID 
           INNER JOIN dbo.LocationJobDescriptions ON dbo.Location.ID = dbo.LocationJobDescriptions.LocationID 
                  AND dbo.JobDescriptions.ID = dbo.LocationJobDescriptions.JobDescriptionID

               WHERE (dbo.Location.Name = N''PFG-City of Industry'') 
                 AND (dbo.TimePunche.DateWorked >= ' + @startdate + ') 
                 AND (dbo.TimePunche.DateWorked <= ' + @enddate + ') 
                 AND (dbo.JobDescriptions.JobDescription = ''House Keeping/Sanitation'') 
                  OR (dbo.Location.Name = N''PFG-City of Industry'') 
                 AND (dbo.TimePunche.DateWorked >= ' + @startdate + ')  
                 AND (dbo.TimePunche.DateWorked <= ' + @enddate + ') 
                 AND (dbo.JobDescriptions.JobDescription = ''Guard Shack'')
            
            GROUP BY 
            CONVERT(varchar(10), dbo.TimePunche.DateWorked, 101), 
                                 dbo.Employee.LastName + '', '' + dbo.Employee.FirstName + '': '' + dbo.Employee.Login) AS BaseData'

    EXECUTE sp_executesql @sql

1 Ответ

1 голос
/ 02 августа 2020

Вы пытаетесь объединить значения datetime со строковыми значениями без использования CAST () или CONVERT ().

Как уже упоминалось в комментариях, вы можете сделать это с помощью параметризованного запроса, поскольку вы уже вызываете sp_execute sql, например:

DECLARE @ColumnNames NVARCHAR(MAX) = ''
DECLARE @sql NVARCHAR (MAX) = ''
DECLARE @startdate as datetime = '2020-07-19 00:00:00'
DECLARE @enddate as datetime = '2020-07-25 00:00:00';

WITH DateRange(DateData) AS 
(
    SELECT @startdate as Date
    UNION ALL
    SELECT DATEADD(d,1,DateData)
    FROM DateRange 
    WHERE DateData < @enddate
)
SELECT @ColumnNames += QUOTENAME(CONVERT(varchar(10),DateData,101)) +','
FROM DateRange
OPTION (MAXRECURSION 0);

SET @ColumnNames = LEFT(@ColumnNames,LEN(@ColumnNames)-1)----------removes final comma

SET @sql =

'SELECT * FROM

(SELECT TOP (100) PERCENT 
CONVERT(varchar(10),dbo.TimePunche.DateWorked,101) AS DateWorked, 
                    dbo.Employee.LastName + '', '' + dbo.Employee.FirstName + '': '' + dbo.Employee.Login AS     Employee, 
                SUM(dbo.TimeInOut.HoursWorked) AS Hours
                FROM dbo.TimeInOut 
        INNER JOIN dbo.TimePunche ON dbo.TimeInOut.TimepuncheID = dbo.TimePunche.ID 
        INNER JOIN dbo.Location 
        INNER JOIN dbo.Employee ON dbo.Location.ID = dbo.Employee.LocationID ON dbo.TimePunche.EmployeeID = dbo.Employee.ID 
        INNER JOIN dbo.JobDescriptions ON dbo.TimeInOut.JobDescriptionID = dbo.JobDescriptions.ID 
        INNER JOIN dbo.LocationJobDescriptions ON dbo.Location.ID = dbo.LocationJobDescriptions.LocationID 
                AND dbo.JobDescriptions.ID = dbo.LocationJobDescriptions.JobDescriptionID

            WHERE (dbo.Location.Name = N''PFG-City of Industry'') 
                AND (dbo.TimePunche.DateWorked >= @1) 
                AND (dbo.TimePunche.DateWorked <= @2) 
                AND (dbo.JobDescriptions.JobDescription = ''House Keeping/Sanitation'') 
                OR (dbo.Location.Name = N''PFG-City of Industry'') 
                AND (dbo.TimePunche.DateWorked >= @1)  
                AND (dbo.TimePunche.DateWorked <= @2) 
                AND (dbo.JobDescriptions.JobDescription = ''Guard Shack'')
        
        GROUP BY 
        CONVERT(varchar(10), dbo.TimePunche.DateWorked, 101), 
                                dbo.Employee.LastName + '', '' + dbo.Employee.FirstName + '': '' + dbo.Employee.Login) AS BaseData'

-->>-- Note the @params definition of @1 and @2 as datetime types here...
EXECUTE sp_executesql @sql, N'@1 datetime, @2 datetime', @startdate, @enddate;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...