sql003.summa_propisju
SQL003. Сумма прописью
Версии сервера
0.9 | 1.0 | 1.5.3 | 1.5.4 | 1.5.5 | 2.0 | 2.0.3 | 2.0.4 | 2.1 | 2.5 | 3.0 |
---|---|---|---|---|---|---|---|---|---|---|
- | - | - | - | - | - | - | - | Да | Да | Да |
Описание
Данная хранимая процедура преобразует переданное ей в качестве параметра значение суммы в текстовое представление.
Ограничения:
- В области строковых констант хранимая процедура может быть изменена под любой язык, но корректно алгоритм будет работать только на восточно-славянской группе языков (русский, белорусский, украинский), имеющих одинаковые правила склонения числительных.
- Данная хранимая процедура будет корректно работать только на «двухуровневых» валютах (доллар-цент, рубль-копейка, грывня-копийка) с отношением 1/100 старшего уровня к младшему (на момент написания данной статьи это практически все валюты мира). Данная хранимая процедура не может использоваться в многоуровневых валютах (например, валюта Соединеннго Королевства до реформы 1972г., имевшая в составе несколько уровней: фунт-шиллинг(стерлинг)-пенс) и валютах, имеющих отношение верхнего уровня к нижнему, отличное от 1/100 (например, валюта Соединеннго Королевства до реформы 1972г., где: 1 фунт = 12 шиллингов(стерлингов)).
Пример
SET TERM ^ ; CREATE OR ALTER PROCEDURE CURRENCYSTR ( VAL NUMERIC(15,2), LANG VARCHAR(2), SHOWCURRENCY INTEGER) RETURNS ( CURR_STR VARCHAR(1000)) AS DECLARE variable RAZRYAD VARCHAR(50); DECLARE variable RAZRYAD_IDX VARCHAR(28); DECLARE variable HUNDREDS VARCHAR(64); DECLARE variable HUNDREDS_IDX VARCHAR(30); DECLARE variable TENS VARCHAR(69); DECLARE variable TENS_IDX VARCHAR(40); DECLARE variable ONES VARCHAR(139); DECLARE variable ONES_IDX VARCHAR(100); DECLARE variable SIGN_OF_VAL VARCHAR(6); DECLARE variable RAZ INTEGER; DECLARE variable CENTS VARCHAR(3); DECLARE variable VAL_STR VARCHAR(20); DECLARE variable NUM VARCHAR(20); DECLARE variable I INTEGER; DECLARE variable BUF VARCHAR(200); DECLARE variable BUF1 VARCHAR(200); DECLARE variable CURR_ABR VARCHAR(5); DECLARE variable MINUS_STR VARCHAR(10); BEGIN lang = UPPER(lang); /* Константы */ IF (lang IS NULL) THEN lang = 'UA'; IF (:lang = 'UA') THEN BEGIN curr_abr = 'грн.'; minus_str = 'мінус'; razryad_idx = /* 2.2 */ '0100010506071307200828113911'; razryad = 'тисячмільйонмільярдтрильйонквадрильйонквінтильйон'; hundreds_idx = /* 2.1 */ '010013046106169257318396458539'; hundreds = 'стодвістітристачотиристап''ятсотшістсотсімсотвісімсотдев''ятсот'; tens_idx = /* 2.2 */ '0100010001080908170522093109400848105810'; tens = 'двадцятьтридцятьсорокп''ятдесятшістдесятсімдесятвісімдесятдев''яносто'; ones_idx = /* 3.2 */ '0010000100001000010300406010050150502003023050280703506041100511006110071120831109411105101151212713'; ones = 'тричотирип''ятьшістьсімвісімдев''ятьдесятьодинадцятьдванадцятьтринадцятьчотирнадцятьп''ятнадцятьшістнадцятьсімнадцятьвісімнадцятьдев''ятнадцять'; END ELSE IF ((:lang = 'RU')) THEN BEGIN curr_abr = 'руб.'; minus_str = 'минус'; razryad_idx = /* 2.2 */ '0100010506071308210829114011'; razryad = 'тисячміллионмиллиардтриллионквадриллионквинтиллион'; hundreds_idx = /* 2.1 */ '010013046106169257328407479569'; hundreds = 'стодвеститристачетырестапятьсотшестьсотсемьсотвосемьсотдевятьсот'; tens_idx = /* 2.2 */ '0100010001080908170522093110410950116109'; tens = 'двадцатьтридцатьсорокпятьдесятшестьдесятсемьдесятвосемьдесятдевяносто'; ones_idx = /* 3.2 */ '0010000100001000010300406010040140501904023060290603506041110521006210072120841009411105101151212712'; ones = 'тричетырепятьшестьсемьвосемьдевятьдесятьодиннадцатьдвенадцатьтринадцатьчетырнадцатьпятнадцатьшестнадцатьсемнадцатьвосемнадцатьдевятнадцать'; END IF (showcurrency IS NULL) THEN showcurrency = 0; curr_str = ''; /* Смотрим знак */ IF (val < 0) THEN BEGIN sign_of_val = minus_str||' '; val = -val; END ELSE sign_of_val = ''; /* Выбираем и запоминаем копейки, убираем их из числа */ val_str = CAST(val AS VARCHAR(20)); i = POSITION('.' IN val_str); cents = lpad(SUBSTRING(val_str FROM i+1 FOR 2), 2, '0'); -- val_str = lpad(substring(val_str FROM 1 FOR i-1), ((i+1)/3*3), '0'); val_str = lpad(SUBSTRING(val_str FROM 1 FOR i-1), (trunc((i+1)/3)*3), '0'); /* Разбираем число */ raz = 0; curr_str = ''; while (val_str != '') do BEGIN /* Берём триаду символов */ num = RIGHT(val_str, 3); /* Если не нулевое число */ IF (num != '000') THEN BEGIN /* Берём сотни */ i = CAST(SUBSTRING(num FROM 1 FOR 1) AS INT); buf = SUBSTRING(hundreds FROM CAST(SUBSTRING(hundreds_idx FROM i*3+1 FOR 2) AS INT) FOR CAST(SUBSTRING(hundreds_idx FROM i*3+3 FOR 1) AS INT)); /* Далее десятки */ /* Для "десятнадцатых" упрощённая обработка */ IF (SUBSTRING(num FROM 2 FOR 1) = '1') THEN BEGIN /* Вставляем нужную "десятнадцать" */ i = CAST(SUBSTRING(num FROM 2 FOR 2) AS INT); buf1 = SUBSTRING(ones FROM CAST(SUBSTRING(ones_idx FROM i*5+1 FOR 3) AS INT) FOR CAST(SUBSTRING(ones_idx FROM i*5+4 FOR 2) AS INT)); IF (buf != '') THEN buf = buf || ' '; buf = buf || buf1; END ELSE /* Для "нормальных" чисел своя обработка */ BEGIN /* Десятки */ i = CAST(SUBSTRING(num FROM 2 FOR 1) AS INT); buf1 = SUBSTRING(tens FROM CAST(SUBSTRING(tens_idx FROM i*4+1 FOR 2) AS INT) FOR CAST(SUBSTRING(tens_idx FROM i*4+3 FOR 2) AS INT)); IF (buf != '' AND buf1 != '') THEN buf = buf || ' '; buf = buf || buf1; /* Единицы */ i = CAST(SUBSTRING(num FROM 3 FOR 1) AS INT); /* Смотрим количество для нужного окончания */ IF (i = 1) THEN BEGIN IF (:lang = 'UA') THEN BEGIN IF (raz IN (0,1)) THEN buf1 = 'одна'; ELSE buf1 = 'один'; END ELSE IF (:lang = 'RU') THEN BEGIN IF (raz = 1) THEN buf1 = 'одна'; ELSE buf1 = 'один'; END END ELSE IF (i = 2) THEN BEGIN IF (:lang = 'UA') THEN BEGIN IF (raz IN (0,1)) THEN buf1 = 'дві'; ELSE buf1 = 'два'; END ELSE IF (:lang = 'RU') THEN BEGIN IF (raz = 1) THEN buf1 = 'две'; ELSE buf1 = 'два'; END END ELSE buf1 = SUBSTRING(ones FROM CAST(SUBSTRING(ones_idx FROM i*5+1 FOR 3) AS INT) FOR CAST(SUBSTRING(ones_idx FROM i*5+4 FOR 2) AS INT)); IF (buf != '' AND buf1 != '') THEN buf = buf || ' '; buf = buf || buf1; END /* Разряд числа */ buf1 = SUBSTRING(razryad FROM CAST(SUBSTRING(razryad_idx FROM raz*4+1 FOR 2) AS INT) FOR CAST(SUBSTRING(razryad_idx FROM raz*4+3 FOR 2) AS INT)); IF (buf1 != '') THEN BEGIN /* Подбор окончания для разряда */ IF (:lang = 'UA') THEN BEGIN IF (i = 1) THEN BEGIN IF (raz = 1) THEN buf1 = buf1 || 'а'; END ELSE IF (i IN (2,3,4)) THEN BEGIN IF (raz = 1) THEN buf1 = buf1 || 'и'; ELSE IF (raz > 1) THEN buf1 = buf1 || 'а'; END ELSE IF (raz > 1) THEN buf1 = buf1 || 'ів'; END ELSE IF (:lang = 'RU') THEN BEGIN IF (i = 1) THEN BEGIN IF (raz = 1) THEN buf1 = buf1 || 'а'; END ELSE IF (i IN (2,3,4)) THEN BEGIN IF (raz = 1) THEN buf1 = buf1 || 'и'; ELSE IF (raz > 1) THEN buf1 = buf1 || 'а'; END ELSE IF (raz > 1) THEN buf1 = buf1 || 'ов'; END buf = buf || ' ' || buf1; END END ELSE buf = ''; /* Присоединяем обработанную триаду к результату */ IF (curr_str != '' AND buf != '') THEN buf = buf || ' '; curr_str = buf || curr_str; /* Переходим к следующей триаде */ val_str = LEFT(val_str, CHAR_LENGTH(val_str)-3); /* Увеличиваем счётчик разряда */ raz = raz + 1; END /* Припысываем знак */ curr_str = sign_of_val || curr_str; /* Делаем первую букву прописной */ curr_str = UPPER(SUBSTRING(curr_str FROM 1 FOR 1)) || SUBSTRING(curr_str FROM 2); /* Флаг "показать название валюты" */ IF (showcurrency != 0) THEN BEGIN IF (curr_str != '' ) THEN curr_str = curr_str || ' '||curr_abr||' '; curr_str = curr_str || cents || ' коп.'; END suspend; END^ SET TERM ; ^ GRANT EXECUTE ON PROCEDURE CURRENCYSTR TO SYSDBA;
См. также
Источник
Форум: sql.ru,
Автор: WildSery, (Sp1r1t добавил поддержку украинской валюты)
Пост: http://sql.ru/forum/actualthread.aspx?tid=628590&pg=-1#6717281
sql003.summa_propisju.txt · Последнее изменение: 2011/07/26 01:49 — peaktop
Обсуждение
ХМ…. не компилится… Говорит, что функции «position» не бывает!;)
обновите сервер до версии 2,1