date s_date
日付フィールド( )と説明フィールド( )を含むテーブルがありますvarchar2(n) desc
。私が必要とするのは、desc
フィールドを解析し、有効なオラクルの日付が含まれている場合は、この日付を切り取り、s_date
それがnull
.
しかし、もう 1 つの条件がありますdesc
。0 または >1 の場合 - 何も更新しないでください。
正規表現を使用して、このかなり醜いソリューションを思いついたときまでに:
----------------------------------------------
create or replace function to_date_single( p_date_str in varchar2 )
return date
is
l_date date;
pRegEx varchar(150);
pResStr varchar(150);
begin
pRegEx := '((0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.](19|20)\d\d)((.|\n|\t|\s)*((0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.](19|20)\d\d))?';
pResStr := regexp_substr(p_date_str, pRegEx);
if not (length(pResStr) = 10)
then return null;
end if;
l_date := to_date(pResStr, 'dd.mm.yyyy');
return l_date;
exception
when others then return null;
end to_date_single;
----------------------------------------------
update myTable t
set t.s_date = to_date_single(t.desc)
where t.s_date is null;
----------------------------------------------
しかし、動作が非常に遅いです (各レコードで 1 秒以上、約 30000 レコードを更新する必要があります)。どういうわけか機能を最適化することは可能ですか? 多分それは正規表現なしで物事を行う方法ですか? 他のアイデアはありますか?
どんなアドバイスでも大歓迎です:)
編集:
わかりました、多分それは誰かに役立つでしょう。次の正規表現は、うるう年のチェックを含め、1 か月の日数を考慮して、有効な日付 (DD.MM.YYYY) のチェックを実行します。
(((0[1-9]|[12]\d|3[01])\.(0[13578]|1[02])\.((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\.(0[13456789]|1[012])\.((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\.02\.((19|[2-9]\d)\d{2}))|(29\.02\.((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))
@Davidが提案したクエリで使用しました(受け入れられた回答を参照)が、「ベンチマーク」目的のためだけに(行ごとに正規表現が1つ少ないため、行ごとに正規表現が1つ少ないため)select
代わりに試しました。update
regexp_substr
ハードウェア、ソフトウェア、および特定の DB 設計に依存するため、数値はおそらくここではあまりわかりませんが、36K レコードを選択するのに約 2 分かかりました。更新は遅くなりますが、それでも妥当な時間になると思います。