Собственно описание проблемы:
Обратился ко мне мой старый товарищ, с просьбой посодействовать в поиске одной ошибке, которая у него возникала при создании распределенной базы данных. Текст ошибки приблизительно такой:
Дата ‘01.01.0001 00:00:00’ не может быть записана в базу данных на MS SQL Server с нулевым смещением дат.
Задача стояла в следующем, чтоб пройтись по всем таблицам базы и найти, где накосячили доблестные работницы финансовой службы.
Решение:
1. Выполняем на SQL следующий код:
SET NOCOUNT ON;
DECLARE @tablename varchar(255);
DECLARE @sql_str varchar(1000);
DECLARE @WrongData varchar(15);
DECLARE @CountRec Int;
DECLARE tables CURSOR FOR
SELECT TABLE_SCHEMA + '.' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE';
OPEN tables;
-- кривая дата
SELECT @WrongData = '01.01.0001 00:00:00';
FETCH NEXT
FROM tables
INTO @tablename;
WHILE @@FETCH_STATUS = 0
BEGIN
---- проверка на дату в документах и журналах
IF col_length(N''+@tablename,'_Date_Time') is not null
BEGIN
SELECT @sql_str = 'SELECT * INTO _ResWrongDate FROM ' + @tablename + ' WHERE _Date_Time<'+''''+@WrongData+''''+'';
EXEC(@sql_str)
SELECT @CountRec = (SELECT COUNT(*) FROM _ResWrongDate);
IF @CountRec > 0
BEGIN
PRINT('Неккоректная дата в таблице '+@tablename+' . записей '+ LTrim(Str(@CountRec)));
END
DROP TABLE _ResWrongDate;
END;
-- в регистрах
IF col_length(N''+@tablename,'_Period') is not null
BEGIN
SELECT @sql_str = 'SELECT * INTO _ResWrongDate FROM ' + @tablename + ' WHERE _Period<'+''''+@WrongData+''''+'';
EXEC(@sql_str)
SELECT @CountRec = (SELECT COUNT(*) FROM _ResWrongDate);
IF @CountRec > 0
BEGIN
PRINT('Неккоректная дата в регистре '+@tablename+' . записей '+ LTrim(Str(@CountRec)));
END
DROP TABLE _ResWrongDate;
END;
FETCH NEXT
FROM tables
INTO @tablename;
END;
CLOSE tables;
DEALLOCATE tables;
GO
Получаем все названия таблиц в которых присутствует некорректная дата.
Либо обработкой, либо сами с помощью команды ПолучитьСтруктуруХраненияБазыДанных находим, что это за документ или регистр.
Находим этот объект, исправляем корректную дату.
В нашем случае дата выдачи паспорта человеку была аж 01.01.0001. Долгожитель попался 🙂
А если проблемная дата будет не в «Периоде», а где-то еще? Лучше уж все колонки соответствующего типа проверить.
Показать
Ну задачи колонки проверить небыло. К тому же явно выгрузка валится не из за реквизитов документов, а из за выгрузки движений регистра.
SQL2008R2 EngStd на типовых БП 3 и не типовой УПП:
Msg 242, Level 16, State 3, Line 1
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated.
(2) таки да, валится ежели участвует в первичных ключах-индексах
SELECT @WrongData = ‘01.01.0001 00:00:00’;
Вот в этой строке у вас не корректное значение.
Скорее у вас смещение дат
Поставьте SELECT @WrongData = ‘01.01.2001 00:00:00’;
И да, если база со смещением дат, то к дате надо прибавлять 2000.
И проверять на некорректные значения лучше с даты к примеру ‘01.01.3919 00:00:00’;
(5) SELECT @WrongData = ‘2001-01-01 00:00:00’; помогло
(7) ну и DECLARE @WrongData varchar(19); а не 15