Узнайте, какая строка вызвала ошибку - PullRequest
3 голосов
/ 11 мая 2010

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

Проблема в том, что данных слишком много, и мы не можем доверять источникам, потому что могут быть некоторые ошибочные или противоречивые данные.

Например, я потратил почти час на поиск ошибки при разработке с использованием клиентской базы данных, потому что где-то в середине моего большого жирного запроса произошла ошибка преобразования некоторого varchar в datetime. Оказалось, что у них были какие-то даты продаж «2009-02-29», дата выхода за пределы допустимого диапазона. И да, я знаю. Почему это хранилось как varchar? Итак, исходная база данных имеет 3 столбца для дат: «Месяц», «День» и «Год». Я понятия не имею, почему это так, но все же, это так.

Но как, черт возьми, я отнесусь к этому, если источник не заслуживает доверия?

Я не могу ОБРАЩАТЬСЯ с исключениями, мне действительно нужно, чтобы оно вышло на новый уровень с исходным сообщением, но я хотел предоставить некоторую дополнительную информацию, чтобы пользователь мог хотя бы попытаться решить ее, прежде чем позвонить нам.

Поэтому я подумал о том, чтобы показать пользователю номер строки или какой-нибудь идентификатор, который, по крайней мере, дал бы ему представление о том, какую запись он должен исправить. Это также тяжелая работа, потому что будут времена, когда интеграция будет работать до 80000 записей. А при интеграции 80000 записей одно фиктивное сообщение об ошибке: 'Преобразование типа данных varchar в тип данных datetime привело к значению datetime вне диапазона' вообще ничего не значит.

Так что любая идея будет оценена.

О, я использую SQL Server 2005 с пакетом обновления 3.


EDIT:

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

Ответы [ 4 ]

2 голосов
/ 11 мая 2010

Я бы предложил предварительно проверить входящие данные, а при возникновении ошибок отложите запись. Например, проверьте недействительные даты. Скажем, вы найдете 20 в наборе 80K. Вытащите эти 20 в отдельную таблицу, с сообщением об ошибке, прикрепленным к записи. Запустите другую проверку, а затем, наконец, импортируйте оставшиеся (все действительные) записи в нужные целевые таблицы.

Это может оказать слишком сильное влияние на производительность, но позволит вам легко указать на ошибки и позволить их исправить и затем вставить во второй проход.

2 голосов
/ 11 мая 2010

для дат вы можете использовать функцию isdate

select ISDATE('20090229'),ISDATE('20090227')

Я обычно вставляю в промежуточный стол, проверяю, а затем вставляю в реальные таблицы

1 голос
/ 11 мая 2010

Это звучит как стандартная проблема ETL: Извлечение, Преобразование и Загрузка. (Если вам не придется повторять этот запрос снова и снова к одному и тому же набору данных, в этом случае вы в значительной степени будете делать одно и то же, только снова и снова. Итак, насколько критична производительность?)

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

В такой ситуации общие рамки, которые я попытался бы установить, следующие:

  • Начиная с исходных таблиц
  • Создание временного набора таблиц (промежуточных таблиц SQLMenace), которые, как вы знаете, являются согласованными и правильно сформированы (действительные данные, ключи и т. Д.)
  • Напишите «не такой большой и толстый запрос» для этих таблиц

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

1 голос
/ 11 мая 2010

попробуйте что-то вроде этого, чтобы найти строки:

...big fat query here...
WHERE ISDATE(YourBadVarcharColumn)!=1

Загрузить данные в промежуточную таблицу, где большинство столбцов имеют тип varchar и допускают значения NULL, где у вас есть столбец состояния.

Запустите команду UPDATE, например

UPDATE Staging
    SET Status='X'
    WHERE ISDATE(CONVERT(YourCharYear+YourCharMonth+YourCharDat+)!=1 
        OR OtherColumn<4...

Затем просто вставьте из своего промежуточного стола, где Status! = 'X'

INSERT INTO RealTable
        (col1, col2...)
    SELECT
        col1, col2, ...
        where Status!='X'
...