Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle:Converter o valor da moeda em palavras usando PL/SQL


Abaixo, estou dando um exemplo de função armazenada do Oracle para converter o valor da moeda em palavras usando PL/SQL. Por exemplo, o valor de $ 123,45 seria traduzido como cento e vinte e três dólares e quarenta e cinco centavos. Além disso, você pode alterar a moeda na função, por exemplo, Rupees e Paise.

Função Oracle PL/SQL para converter o valor da moeda em palavras


A seguinte função armazenada Oracle PL/SQL aceita um argumento numérico e não tem limitações. Um número pode ser um número decimal, inteiro e negativo. A função quantidade_em_palavras tem uma função dentro de check_if_single , e a função check_if_single tem um n_spell função dentro para converter o valor da moeda em palavras. Eu estava pensando em criar um pacote ao invés dessa função, mas achei que apenas uma função seria mais fácil de manter.
CREATE OR REPLACE FUNCTION amount_in_words (i_amt IN NUMBER)
   RETURN VARCHAR2
IS
   n_dollar   NUMBER;
   n_cents    NUMBER;

   FUNCTION check_if_single (i_num IN NUMBER, currency IN VARCHAR2)
      RETURN VARCHAR2
   IS
      FUNCTION n_spell (i_num IN NUMBER)
         RETURN VARCHAR2
      AS
         TYPE w_Array IS TABLE OF VARCHAR2 (255);

         l_str w_array
               := w_array ('',
                           ' thousand ',
                           ' million ',
                           ' billion ',
                           ' trillion ',
                           ' quadrillion ',
                           ' quintillion ',
                           ' sextillion ',
                           ' septillion ',
                           ' octillion ',
                           ' nonillion ',
                           ' decillion ',
                           ' undecillion ',
                           ' duodecillion ');

         l_num           VARCHAR2 (50) DEFAULT TRUNC (i_num);
         l_is_negative   BOOLEAN := FALSE;
         l_return        VARCHAR2 (4000);
      BEGIN
         IF SIGN (i_num) = -1
         THEN
            l_is_negative := TRUE;
            l_num := TRUNC (ABS (i_num));
         END IF;

         FOR i IN 1 .. l_str.COUNT
         LOOP
            EXIT WHEN l_num IS NULL;

            IF (SUBSTR (l_num, LENGTH (l_num) - 2, 3) <> 0)
            THEN
               l_return :=
                  TO_CHAR (
                     TO_DATE (SUBSTR (l_num, LENGTH (l_num) - 2, 3), 'J'),
                     'Jsp')
                  || l_str (i)
                  || l_return;
            END IF;

            l_num := SUBSTR (l_num, 1, LENGTH (l_num) - 3);
         END LOOP;

         IF NOT l_is_negative
         THEN
            RETURN INITCAP (l_return);
         ELSE
            RETURN 'Negative ' || INITCAP (l_return);
         END IF;
      END n_spell;
   BEGIN
      IF i_num = 1
      THEN
         RETURN 'One ' || currency;
      ELSE
         RETURN n_spell (i_num) || ' ' || currency;
      END IF;
   END check_if_single;
BEGIN
   IF i_amt IS NULL
   THEN
      RETURN '';
   END IF;

   n_dollar := TRUNC (i_amt);
   n_cents := (ABS (i_amt) - TRUNC (ABS (i_amt))) * 100;

   IF NVL (n_cents, 0) > 0
   THEN
      RETURN    check_if_single (n_dollar, 'Dollar')
             || ' and '
             || check_if_single (n_cents, 'Cents');
   ELSE
      RETURN check_if_single (n_dollar, 'Dollar');
   END IF;
END amount_in_words;
/

Teste

SELECT amount_in_words (89378.58) FROM DUAL;

Saída

Eighty-Nine Thousand Three Hundred Seventy-Eight Dollar and Fifty-Eight Cents

Teste em uma tabela

SELECT client_code,
       balance_amt,
       amount_in_words (balance_amt) balance_amount_in_words
  FROM account_balance;

Saída

CLIENT_CODE BALANCE_AMT BALANCE_AMOUNT_IN_WORDS
88499 78849,98 Setenta e oito mil oitocentos e quarenta e nove dólares e noventa e oito centavos
77493 7738829.15 Sete milhões setecentos e trinta e oito mil oitocentos e vinte e nove dólares e quinze centavos
88399 99836662388.98 Noventa e nove bilhões, oitocentos e trinta e seis milhões, seiscentos e sessenta e dois mil, trezentos e oitenta e oito dólares e noventa e oito centavos
97737 -88993.5 Negativo oitenta e oito mil novecentos e noventa e três dólares e cinquenta centavos
88948 998349 Novecentos e noventa e oito mil trezentos e quarenta e nove dólares

Você pode alterar a moeda ao chamar o check_if_single função de amount_in_words função. Por exemplo, mudei para Rupees e Paise na seguinte parte do código PL/SQL:
 IF NVL (n_cents, 0) > 0
   THEN
      RETURN    check_if_single (n_dollar, 'Rupees')
             || ' and '
             || check_if_single (n_cents, 'Paise');
   ELSE
      RETURN check_if_single (n_dollar, 'Rupees');
   END IF;

Teste depois de fazer a alteração

SELECT amount_in_words (7836.58) in_words FROM DUAL;

Saída

Seven Thousand Eight Hundred Thirty-Six Rupees and Fifty-Eight Paise

Talvez você precise mudar a palavra Rupees da posição final para a inicial da linha, dependendo do formato da moeda e que pode ser alterado facilmente na função acima.

Veja também:

  • Utilitário:gerar procedimento PL/SQL para exportar dados de uma tabela em 2 minutos