SQL Server, просмотры и преобразования даты и времени - PullRequest
1 голос
/ 08 октября 2009

Итак, у меня есть базовая таблица, которая выглядит примерно так.

SELECT [BILL_MONTH]
      ,[BILL_YEAR]
      ,[BILLED]
 FROM bill_Detail

Все это varchar.

Я создал представление на основе этой таблицы, которое преобразует год счета и месяц счета в поле даты и времени. Конечно, в полях bill_month и bill_year есть некоторые дерьмовые данные, которые не преобразуются, поэтому в моем представлении есть следующее предложение WHERE.

WHERE   ISDATE(CONVERT(varchar(4), BILL_YEAR)  + '-' + CONVERT(varchar(3), BILL_MONTH) + '-1' ) = 1

Вид работает как чемпион, когда я делаю простой выбор на нем. Нет плохих дат, все вычищено и т. Д. Однако, когда я пытаюсь выполнить какую-либо арифметику дат (dateadd, datediff), я начинаю получать ошибки преобразования.

РЕДАКТИРОВАТЬ: Добавление в фактическом представлении и проверить выбор оператора:

код для просмотра

SELECT  ID
    ,BILLED
    ,Payment_Type
    ,CONVERT(datetime, CONVERT(varchar(4), BILL_YEAR)  + '-'  + CONVERT(varchar(3), BILL_MONTH) + '-1' ) 
    AS BillDate FROM    dbo.Detail AS d WHERE   ISDATE(CONVERT(varchar(4), BILL_YEAR)  + '-' + CONVERT(varchar(3), BILL_MONTH) + '-1' ) = 1 AND     ISNULL(Payment_Code,'') = '' AND        Payment_Type in ('D','I')

Вот оператор выбора, который взрывается.

SELECT ID
  ,[BILLED]
  ,[Payment_Type]
  ,[BillDate] FROM vw_DelinquentDetail where isdate(billdate) = 1

В операторе select появляется следующая ошибка.

Преобразование типа данных char в тип данных datetime привело к значению datetime вне диапазона.

Извините за форматирование кода в первом разделе.

Ответы [ 4 ]

1 голос
/ 08 октября 2009

убедитесь, что вы преобразовали дату в дату и время в представлении:

create table testdates
(BILL_MONTH  varchar(3)
,BILL_YEAR   char(4)
,BILLED char(1)
)

insert into testdates values ('01','2009','y')
insert into testdates values ('02','2009','y')
insert into testdates values ('03','2009','y')
insert into testdates values ('a','bbb','n')

create view testdates_v as
select
CONVERT(datetime,CONVERT(varchar(4), BILL_YEAR)  + '-' + CONVERT(varchar(3), BILL_MONTH) + '-1') as billdate
from testdates
WHERE   ISDATE(CONVERT(varchar(4), BILL_YEAR)  + '-' + CONVERT(varchar(3), BILL_MONTH) + '-1' ) = 1
go

Теперь попробуйте использовать вид:

select billdate from testdates_v

ВЫВОД:

billdate
-----------------------
2009-01-01 00:00:00.000
2009-02-01 00:00:00.000
2009-03-01 00:00:00.000

(3 row(s) affected)


select billdate+1,dateadd(mi,45,billdate) from  testdates_v

выход: * +1010 *

----------------------- -----------------------
2009-01-02 00:00:00.000 2009-01-01 00:45:00.000
2009-02-02 00:00:00.000 2009-02-01 00:45:00.000
2009-03-02 00:00:00.000 2009-03-01 00:45:00.000

(3 row(s) affected)

РЕДАКТИРОВАТЬ после редактирования OP, давая больше кода:

SQL SERVER, вероятно, пытается создать столбец billdate, прежде чем применить WHERE. В результате измените свое представление, выбрав billdate, используя CASE, поэтому оно равно NULL, если недействительная дата:

SELECT  ID
        ,BILLED
        ,Payment_Type
        ,CASE
             WHEN ISDATE(CONVERT(varchar(4), BILL_YEAR)  + '-' + CONVERT(varchar(3), BILL_MONTH) + '-1' ) = 1  THEN CONVERT(datetime, CONVERT(varchar(4), BILL_YEAR)  + '-'  + CONVERT(varchar(3), BILL_MONTH) + '-1' ) 
             ELSE NULL
         END AS BillDate 
    FROM    dbo.Detail AS d 
    WHERE   ISDATE(CONVERT(varchar(4), BILL_YEAR)  + '-' + CONVERT(varchar(3), BILL_MONTH) + '-1' ) = 1 AND         ISNULL(Payment_Code,'') = '' AND                Payment_Type in ('D','I')

При использовании приведенного выше представления ошибка исчезает.

0 голосов
/ 12 мая 2011

Ниже приведен ответ от аналогичного поста , который я сделал на MSDN:

(кредит: Том Купер) [Оптимизатору запросов] разрешено переставлять SQL любым удобным для него способом, если переставленный способ будет возвращать те же результаты. Так оно и происходит: получить строки, выполнить преобразование, а затем удалить ненужные строки. Это, конечно, дает вам ошибку конверсии.

Технически, это ошибка. Поскольку вы получаете результат, который отличается от того, как если бы SQL делал все в стандартном порядке. Но это ошибка, которую Microsoft не собирается исправлять. Причина в том, что изменение порядка действий часто приводит к значительному улучшению производительности. И тестирование, чтобы видеть, могла ли перестановка вызвать ошибку как это, было бы трудно и дорого.

0 голосов
/ 08 октября 2009

Я знаю, что это на самом деле не отвечает на ваш вопрос, но возможно ли для вас просто вернуть необработанное строковое значение в ваш бизнес-код и выполнить все преобразования и вычисления там? Это было бы намного проще и безопаснее.

0 голосов
/ 08 октября 2009

вы не включили предложение select в ваше представление, но вам нужно убедиться, что вы конвертируете столбцы BILL_MONTH] и [BILL_YEAR] вашей базовой таблицы в один столбец datetime в представлении.

...