====== Полезные запросы ====== ===== Версии сервера ===== ^ 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 ^ | - | - | - | - | - | - | - | - | - | - | - | ===== Доступно в ===== [[raznovidnosti_jazyka_sql|DSQL]], [[raznovidnosti_jazyka_sql|ESQL]], [[raznovidnosti_jazyka_sql|ISQL]], [[raznovidnosti_jazyka_sql|PSQL]] ===== Формат ===== ===== Описание ===== полезные запросы, которые можно будет оформить в статью или просто создать страничку ===== Пример ===== если нужно отобрать записи по ключам, то намного быстрее будет засунуть эти ID в строку, распарсить и вытягивать каждую запись по по ключу по отдельности в цикле: CREATE PROCEDURE CONVERT_IDS_TO_ROWS( IDS VARCHAR(32700)) RETURNS ( ID INTEGER) AS DECLARE I INTEGER = 1; DECLARE J INTEGER = 1; BEGIN IDS = TRIM(IDS); WHILE (I <= CHAR_LENGTH(IDS)) DO BEGIN IF (',' = SUBSTRING(IDS FROM I FOR 1)) THEN BEGIN ID = SUBSTRING(IDS FROM J FOR I - J); SUSPEND; I = I + 1; J = I; END I= I + 1; END IF (I > J) THEN BEGIN ID = SUBSTRING(IDS FROM J FOR I - J); SUSPEND; END END CREATE OR ALTER PROCEDURE LIST_TO_ROWS( LST BLOB SUB_TYPE TEXT) RETURNS ( ID INTEGER) AS declare i integer = 1; declare j integer = 1; begin while (i <= char_length(lst)) do begin if (substring(lst from i for 1) = ',') then begin if (i > j) then id = substring(lst from j for i - j); else id = null; suspend; j = i+1; end i = i+1; end if (i > j) then id = substring(lst from j for i - j); else id = null; suspend; end CREATE OR ALTER PROCEDURE LIST_TO_ROWS( LST BLOB SUB_TYPE TEXT) RETURNS ( ID INTEGER) AS declare pos_ int; declare offset int = 1; declare beg int; declare buf varchar(30100); begin while (0=0) do begin buf = substring(lst from offset for 30100); pos_ = 1; beg = 1; while (pos_ <= char_length(buf) and pos_ <= 30000) do begin if (substring(buf from pos_ for 1) = ',') then begin if (pos_ > beg) then id = substring(buf from beg for pos_ - beg); else id = null; suspend; beg = pos_ + 1; end pos_ = pos_ + 1; end if (offset + pos_ - 2 = char_length(lst)) then leave; offset = offset + beg - 1; if (offset > char_length(lst)) then leave; end if (pos_ > beg) then id = substring(buf from beg for pos_ - beg); else id = null; suspend; end Если нужно проверить во входящей строке можно ли её считать числом можно использовать следующую процедуру CREATE PROCEDURE IS_NUMBER ( a_value varchar(32)) returns ( result varchar(10)) as declare variable i integer; declare variable j integer; begin result = 'Фиг'; a_value = trim(a_value); if (a_value is null or char_length(a_value) = 0) then begin suspend; exit; end i = 1; j = CHAR_LENGTH(a_value); while (i <= j) do begin if (substring(a_value from i for 1) between '0' and '9' or (i =1 and substring(a_value from 1 for 1) in ('-', '+') and CHAR_LENGTH(a_value) > 1 )) then result = 'Это число'; else begin result = 'Фиг'; Break; end i = i + 1; end suspend; end CREATE OR ALTER PROCEDURE CURRENCYSTR( VAL NUMERIC(15,2), SHOWCURRENCY INTEGER) RETURNS ( CURR_STR VARCHAR(1000)) AS declare razryad varchar(50); declare razryad_idx varchar(28); declare hundreds varchar(64); declare hundreds_idx varchar(30); declare tens varchar(69); declare tens_idx varchar(40); declare ones varchar(138); declare ones_idx varchar(100); declare sign_of_val varchar(6); declare raz int; declare cents varchar(3); declare val_str varchar(20); declare num varchar(20); declare i int; declare buf varchar(200); declare buf1 varchar(200); begin /* Константы */ razryad_idx = /* 2.2 */ '0100010506071308210829114011'; razryad = 'тысячмиллионмиллиардтриллионквадриллионквинтиллион'; hundreds_idx = /* 2.1 */ '010013046106169257328407479569'; hundreds = 'стодвеститристачетырестапятьсотшестьсотсемьсотвосемьсотдевятьсот'; tens_idx = /* 2.2 */ '0100010001080908170522093110410950116109'; tens = 'двадцатьтридцатьсорокпятьдесятшестьдесятсемьдесятвосемьдесятдевяносто'; ones_idx = /* 3.2 */ '0010000100001000010300406010040140501904023060290603506041110521006210072120841009411105101151212712'; ones = 'тричетырепятьшестьсемьвосемьдевятьдесятьодиннадцатьдвенадцатьтринадцатьчетырнадцатьпятнадцатьшестнадцатьсемнадцатьвосемнадцатьдевятнадцать'; if (ShowCurrency is null) then ShowCurrency = 0; curr_str = ''; /* Смотрим знак */ if (val < 0) then begin sign_of_val = 'минус '; 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'); /* Разбираем число */ 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 (raz = 1) then buf1 = 'одна'; else buf1 = 'один'; end else if (i = 2) then begin if (raz = 1) then buf1 = 'две'; else buf1 = 'два'; 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 (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 || 'ов'; 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 = 1) then curr_str = curr_str || ' руб. ' || cents || ' коп.'; suspend; end WITH RECURSIVE RELATIONS AS ( SELECT DISTINCT RC_1.RDB$RELATION_NAME AS RN1, RC_2.RDB$RELATION_NAME AS RN2 FROM RDB$RELATION_CONSTRAINTS RC_1 JOIN RDB$REF_CONSTRAINTS REC_2 ON REC_2.RDB$CONST_NAME_UQ = RC_1.RDB$CONSTRAINT_NAME AND RC_1.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' JOIN RDB$RELATION_CONSTRAINTS RC_2 ON RC_2.RDB$CONSTRAINT_NAME = REC_2.RDB$CONSTRAINT_NAME AND RC_2.RDB$CONSTRAINT_TYPE = 'FOREIGN KEY' WHERE RC_1.RDB$RELATION_NAME <> RC_2.RDB$RELATION_NAME ), RELATIONS_TREE AS ( SELECT DISTINCT 1 AS LVL, RN1 AS RN_ID, CAST(NULL AS VARCHAR(32)) AS RN_PARENT FROM RELATIONS UNION ALL SELECT RT.LVL + 1, R.RN1, R.RN2 FROM RELATIONS R JOIN RELATIONS_TREE RT ON R.RN2 = RT.RN_ID ), RELATION_REFS AS ( SELECT RN_ID, SUM(LVL) AS REFS_COUNT FROM RELATIONS_TREE GROUP BY 1 ) SELECT RR.RDB$RELATION_NAME AS RELATION_NAME, COALESCE(RT.REFS_COUNT, 0) FROM RDB$RELATIONS RR LEFT JOIN RELATION_REFS RT ON RT.RN_ID = RR.RDB$RELATION_NAME WHERE RR.RDB$VIEW_BLR IS NULL AND COALESCE(RR.RDB$SYSTEM_FLAG, 0) = 0 ORDER BY 2 DESC ===== См. также ===== [[]] ===== Источник ===== 2008-05-12irebird%\doc\