1 Şubat 2013 Cuma

[ORACLE] IS_NUMERIC


Merhabalar,

Hemen hemen tüm uygulamalarda ve senaryolarda kullanmak durumunda olduğumuz “bir string numeric mi değil mi?” methodu için Steven Feuerstein PL/SQL Programming kitabında şöyle bir yöntemi tarif eder:

CREATE OR REPLACE FUNCTION is_numeric (p_value VARCHAR2)
  RETURN BOOLEAN IS
  v_test_number NUMBER;
BEGIN
  v_test_number := to_number(p_value);
  RETURN TRUE;
EXCEPTION
  WHEN value_error THEN
    RETURN FALSE;
END is_numeric;

Yani string numeric değilse to_number conversion sırasında value_error exception’a düşecek ve false değer dönecek, diğer türlü true diyecek ve işlem doğru biçimde tamamlanacak. 



Bir sistem için optimizasyon çalışmaları yürütüyordum ve aklıma daha süratli bir yöntem olup olamayacağı geldi. Bunun için 11g de tanıtılan regular expression yönteminin doğru olabileceğini düşünüp aşağıdaki gibi bir program yazdım:

CREATE OR REPLACE FUNCTION is_numeric(i_value IN VARCHAR2)
  RETURN BOOLEAN IS
BEGIN

  RETURN length(i_value) = regexp_count(i_value, '[[:digit:]]');

END is_numeric;

Regexp_count gelen string içerisindeki digit sayısını arıyor ve gelen stringin uzunluğu ile aynı ise numeric oluyor, diğer türlü false değeri dönüyor. Buradaki kritik soru hangisi daha performanslı (zaten amaç ta buydu). Ben performans testlerini yapabilmek için program isimlerini is_numeric_exceptive (ilk örnek) ve is_numeric_regexp (ikinci örnek) olarak değiştirdim.

Sonuç:
Regular Expression: 74
Exceptive: 84


DECLARE
  l_result BOOLEAN;
  l_start PLS_INTEGER;
  l_end   PLS_INTEGER;
BEGIN

  l_start := dbms_utility.get_cpu_time;

  FOR i IN 1 .. 100000 LOOP
    l_result := is_numeric_regexp(dbms_random.string('X', 5));
  END LOOP;

  l_end := dbms_utility.get_cpu_time;

  dbms_output.put_line('Regular Expression: ' || to_char(l_end - l_start));

  ------------------------------------------------------

  l_start := dbms_utility.get_cpu_time;

  FOR i IN 1 .. 100000 LOOP
    l_result := is_numeric_exceptive(dbms_random.string('X', 5));
  END LOOP;

  l_end := dbms_utility.get_cpu_time;

  dbms_output.put_line('Exceptive: ' || to_char(l_end - l_start));

END;

Hiç yorum yok:

Yorum Gönder