Я думаю, что основная проблема в том, как источник OLEDB определяет тип данных параметра, я не нашел официальной документации, в которой это упоминалось, но вы можете провести небольшой эксперимент, чтобы увидеть это:
Попробуйте написать следующий запрос в команде SQL в источнике OLEDB:
SELECT ? as Column1
А затем попытайтесь разобрать запрос, вы получите следующую ошибку:
Тип параметра для '@ P1' не может быть однозначно выведен; две возможности: «sql_variant» и «xml».
Это означает, что анализатор запросов пытается выяснить, какой тип данных у этого параметра, он не связан с типом данных переменной, который вы ему сопоставили.
Затем попробуйте написать следующий запрос:
SELECT CAST(? AS INT) AS Column1
А затем попытавшись разобрать запрос, вы получите:
Оператор SQL был успешно проанализирован.
Теперь давайте применим этот эксперимент к вашему запросу:
Попробуйте SELECT CAST(GETDATE() - ? AS DATE) as Column1
, и вы получите неправильное значение, затем попробуйте SELECT CAST(GETDATE() - CAST(? AS INT) AS DATE) AS Column1
, и вы получите правильное значение.
Обновление 1 - информация из официальной документации
Из следующего Источник OLEDB - Документация :
Параметры сопоставляются с переменными, которые предоставляют значения параметров во время выполнения. Переменные обычно являются пользовательскими переменными, хотя вы также можете использовать системные переменные, которые предоставляет Integration Services. Если вы используете пользовательские переменные, убедитесь, что вы установили для типа данных тип, совместимый с типом данных столбца, на который ссылается сопоставленный параметр.
Это означает, что тип данных параметра не связан с типом данных переменной.
Обновление 2 - эксперименты с использованием SQL Profiler
В качестве эксперимента я создал пакет служб SSIS, который экспортирует данные из источника OLEDB в пункт назначения набора записей. Источник данных является результатом следующего запроса:
SELECT *
FROM dbo.DatabaseLog
WHERE PostTime < CAST(GETDATE() - ? as date)
И параметр ?
сопоставляется с переменной типа Int32
и имеет значение 10
Перед выполнением пакета я запустил трассировку SQL Profiler в экземпляре SQL Server, после выполнения пакета в трассировку были записаны следующие запросы:
exec [sys].sp_describe_undeclared_parameters N'SELECT *
FROM dbo.DatabaseLog
WHERE PostTime < CAST(GETDATE() -@P1 as date)'
declare @p1 int
set @p1=1
exec sp_prepare @p1 output,N'@P1 datetime',N'SELECT *
FROM dbo.DatabaseLog
WHERE PostTime < CAST(GETDATE() -@P1 as date)',1
select @p1
exec sp_execute 1,'1900-01-09 00:00:00'
exec sp_unprepare 1
Первая команда exec [sys].sp_describe_undeclared_parameters
должна описать тип параметра, если мы запустим его отдельно, он вернет следующую информацию:
Показывает, что тип данных параметра рассматривается как datetime
.
Другие команды показывают странное утверждение:
- Сначала значение
@P1
устанавливается на 1
- Окончательный запрос выполняется со следующим значением
1900-01-09 00:00:00
Обсуждение
В ядре базы данных SQL Server базовое значение datetime равно 1900-01-01 00:00:00
, которое можно получить, выполнив следующий запрос:
declare @dt datetime
set @dt = 0
Select @dt
С другой стороны, в SSIS:
Структура даты, состоящая из года, месяца, дня, часа, минуты, секунд и дробных секунд. Дробные секунды имеют фиксированную шкалу из 7 цифр.
Тип данных DT_DATE реализован с использованием 8-байтового числа с плавающей запятой. Дни представлены приращениями целых чисел, начиная с 30 декабря 1899 , а полночь - нулевое время. Часовые значения выражаются как абсолютное значение дробной части числа. Однако значение с плавающей запятой не может представлять все реальные значения; следовательно, существуют ограничения на диапазон дат, которые могут быть представлены в DT_DATE.
С другой стороны, DT_DBTIMESTAMP представлен структурой, которая внутренне имеет отдельные поля для года, месяца, дня, часов, минут, секунд и миллисекунд. Этот тип данных имеет большие ограничения на диапазоны дат, которые он может представлять.
Исходя из этого, я думаю, что существует разница между базовым значением datetime между типом данных даты SSIS (1899-12-30
) и datetime SQL Server (1900-01-01
), что приводит к разнице в два дня при выполнении неявное преобразование для оценки значения параметра.
Ссылки