Задача такая. В базу из текстового файла грузятся данные. Надо проверить являются ли эти данные датой. Дело в том, что формат входных данных заранее не известен. Это может быть 31.12.2007 или 12.31.2007, или 31 Дек 2007, или Дек 31 2007, а может и вообще датой не быть. При чем как выгружали данные в файл — неизвестно. Форматы могут чередоваться. как лучше поступить?
Я делаю так:
DECLARE
date_variable VARCHAR2 (100) := TO_CHAR (SYSDATE, 'mm dd yyyy');
FUNCTION is_date (STRING VARCHAR2)
RETURN BOOLEAN
IS
temp DATE;
BEGIN
temp := TO_DATE (STRING);
RETURN TRUE;
EXCEPTION
WHEN OTHERS
THEN
RETURN FALSE;
END;
BEGIN
IF is_date (date_variable)
THEN
DBMS_OUTPUT.put_line (date_variable || ' - Date.');
ELSE
DBMS_OUTPUT.put_line (date_variable || ' - Not date.');
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM);
END;
Но это естественно не выход, т.к. формат по умолчанию в базе.
П>Задача такая. В базу из текстового файла грузятся данные. Надо проверить являются ли эти данные датой. Дело в том, что формат входных данных заранее не известен. Это может быть 31.12.2007 или 12.31.2007, или 31 Дек 2007, или Дек 31 2007, а может и вообще датой не быть. При чем как выгружали данные в файл — неизвестно. Форматы могут чередоваться. как лучше поступить?
П>Я делаю так:
П>[sql] П>DECLARE П> date_variable VARCHAR2 (100) := TO_CHAR (SYSDATE, 'mm dd yyyy');
П>Но это естественно не выход, т.к. формат по умолчанию в базе.
Хотел написать что-нибудь умное и универсальное, но что-то в голову не приходит, може люи поумнее подскажут. Я бы сделал (собственно и делаю, тоже прихоится загружать подобное, но у меня только три варианта формата даты, так что проще) последовательные попытки преобразования строки в дату с разными форматами. То есть в обработчике exception опять to_date, но с другой маской и так далее.
Вполне возможно, есть и более красивый и универсальный путь.
Здравствуйте, TMU, Вы писали:
П>>Задача такая. В базу из текстового файла грузятся данные. Надо проверить являются ли эти данные датой. Дело в том, что формат входных данных заранее не известен. Это может быть 31.12.2007 или 12.31.2007, или 31 Дек 2007, или Дек 31 2007, а может и вообще датой не быть. При чем как выгружали данные в файл — неизвестно. Форматы могут чередоваться. как лучше поступить?
П>>Я делаю так:
П>>[sql] П>>DECLARE П>> date_variable VARCHAR2 (100) := TO_CHAR (SYSDATE, 'mm dd yyyy');
П>>Но это естественно не выход, т.к. формат по умолчанию в базе.
TMU>Хотел написать что-нибудь умное и универсальное, но что-то в голову не приходит, може люи поумнее подскажут. Я бы сделал (собственно и делаю, тоже прихоится загружать подобное, но у меня только три варианта формата даты, так что проще) последовательные попытки преобразования строки в дату с разными форматами. То есть в обработчике exception опять to_date, но с другой маской и так далее. TMU>Вполне возможно, есть и более красивый и универсальный путь.
Здравствуйте, Пингвиненок, Вы писали:
П>как лучше поступить?
Пробовать несколько возможных форматов. Заранее определенных и упорядоченных по по приоритету. Но и это не гарантирует 100% точного распознавания (например 05.10.2005 — 10.05.2005).
Самое лучшее IMHO — не иметь дела с такими данными. То есть вычистить их до загрузки. Обычно 90% вычищается автоматически (perl, awk и т.п.), остальное руками и глазами.
W>Пробовать несколько возможных форматов. Заранее определенных и упорядоченных по по приоритету. Но и это не гарантирует 100% точного распознавания (например 05.10.2005 — 10.05.2005).
W>Самое лучшее IMHO — не иметь дела с такими данными. То есть вычистить их до загрузки. Обычно 90% вычищается автоматически (perl, awk и т.п.), остальное руками и глазами.
Лучше быть здоровым и богатым . К сожалению, приходится иногда иметь дело с данными из источников, на которые повлиять невозможно
Лови. Список доступных форматов можешь пополнить в курсоре:
DECLARE
date_variable VARCHAR2 (100) := TO_CHAR (SYSDATE, 'mon dd yyyy');
FUNCTION is_date (STRING VARCHAR2)
RETURN BOOLEAN
IS
CURSOR c (separator VARCHAR2)
IS
SELECT f
FROM (SELECT UPPER (d.d || separator || m.m || separator || y.y
) AS f
FROM (SELECT 'DD' AS d
FROM DUAL) d,
(SELECT 'MM' AS m
FROM DUAL
UNION ALL
SELECT 'RM' AS m
FROM DUAL
UNION ALL
SELECT 'MONTH' AS m
FROM DUAL
UNION ALL
SELECT 'MON' AS m
FROM DUAL) m,
(SELECT 'YYYY' AS y
FROM DUAL
UNION ALL
SELECT 'SYYYY' AS y
FROM DUAL
UNION ALL
SELECT 'IYYY' AS y
FROM DUAL
UNION ALL
SELECT 'YYY' AS y
FROM DUAL
UNION ALL
SELECT 'YY' AS y
FROM DUAL
UNION ALL
SELECT 'Y' AS y
FROM DUAL
UNION ALL
SELECT 'IYY' AS y
FROM DUAL
UNION ALL
SELECT 'IY' AS y
FROM DUAL
UNION ALL
SELECT 'I' AS y
FROM DUAL
UNION ALL
SELECT 'Y,YYY' AS y
FROM DUAL
UNION ALL
SELECT 'YEAR' AS y
FROM DUAL
UNION ALL
SELECT 'SYEAR' AS y
FROM DUAL
UNION ALL
SELECT 'RR' AS y
FROM DUAL) y
UNION ALL
SELECT UPPER (m.m || separator || d.d || separator || y.y
) AS f
FROM (SELECT 'DD' AS d
FROM DUAL) d,
(SELECT 'MM' AS m
FROM DUAL
UNION ALL
SELECT 'RM' AS m
FROM DUAL
UNION ALL
SELECT 'MONTH' AS m
FROM DUAL
UNION ALL
SELECT 'MON' AS m
FROM DUAL) m,
(SELECT 'YYYY' AS y
FROM DUAL
UNION ALL
SELECT 'SYYYY' AS y
FROM DUAL
UNION ALL
SELECT 'IYYY' AS y
FROM DUAL
UNION ALL
SELECT 'YYY' AS y
FROM DUAL
UNION ALL
SELECT 'YY' AS y
FROM DUAL
UNION ALL
SELECT 'Y' AS y
FROM DUAL
UNION ALL
SELECT 'IYY' AS y
FROM DUAL
UNION ALL
SELECT 'IY' AS y
FROM DUAL
UNION ALL
SELECT 'I' AS y
FROM DUAL
UNION ALL
SELECT 'Y,YYY' AS y
FROM DUAL
UNION ALL
SELECT 'YEAR' AS y
FROM DUAL
UNION ALL
SELECT 'SYEAR' AS y
FROM DUAL
UNION ALL
SELECT 'RR' AS y
FROM DUAL) y) f;
temp DATE;
res BOOLEAN;
BEGIN
res := TRUE;
FOR r IN c ('.')
LOOP
BEGIN
temp := TO_DATE (STRING, r.f);
RETURN TRUE;
EXCEPTION
WHEN OTHERS
THEN
NULL;
END;
END LOOP;
RETURN FALSE;
EXCEPTION
WHEN OTHERS
THEN
RETURN FALSE;
END;
BEGIN
IF is_date (date_variable)
THEN
DBMS_OUTPUT.put_line (date_variable || ' - Date.');
ELSE
DBMS_OUTPUT.put_line (date_variable || ' - Not date.');
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM);
END;
Здравствуйте, wildwind, Вы писали:
W>Здравствуйте, Пингвиненок, Вы писали:
П>>Здравствуйте, TMU, Вы писали:
W>
П>> EXCEPTION
П>> WHEN OTHERS
П>> THEN
П>> RETURN FALSE;
П>> END;
W>
W>За такое у нас бъют линейкой по рукам.
Почему? Функция служит для очистки данных. Проверяет строку на то, является ли она датой и всегда должна возвращать либо TRUE либо FALSE. После очистки "грязные данные" все равно проверяются.
Здравствуйте, wildwind, Вы писали:
W>Здравствуйте, Пингвиненок, Вы писали:
П>>Здравствуйте, TMU, Вы писали:
W>
П>> EXCEPTION
П>> WHEN OTHERS
П>> THEN
П>> RETURN FALSE;
П>> END;
W>
W>За такое у нас бъют линейкой по рукам.
Предложи свой вариант, когда поток данных будет очищаться автоматически и надо отсеивать "грязные" данные. Есть 2 варианта: либо они попадают в таблицу назначения, либо в таблицу с ошибками. Третьего не дано. Процесс должен быть автоматизирован.