2009-10-08 4 views
1

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

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

Все есть варчар.

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

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

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

EDIT: Добавление в реальных целях и тест оператора выбора:

код для представления

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 указывает, где появляется следующее сообщение об ошибке.

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

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

+0

Опубликовать Sql, который не работает. – jfar

+0

см. Мое редактирование, у меня есть решение для вас –

ответ

1

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

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 

выход :

----------------------- ----------------------- 
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) 

EDIT после редактирования 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

Я счастливый человек. Спасибо КМ. –

0

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

0

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

0

Ниже ответ от a similar post, что я сделал на MSDN:

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

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

Смежные вопросы