В процессе формирования…
Важно!
1. При копировании текстов функций этого раздела, следует «крупно иметь в виду», что существенная часть функций вызывает другие функции (размещенные в этом разделе, а также и в других разделах тоже).
2. Чтобы компенсировать этот момент — в конце страницы можно скачать исходные тексты всех функций в формате PG-backup (SQL-текст).
- str_words_count — вычислить кол-во слов в заданной строке;
- str_word_by_num — получить слово из заданной строки по заданному номеру;
- str_sets_intersect — проверка пересечения 2-х множеств, заданных в виде строк символов;
- str_reverse — инвертирвать заданную строку;
- str_replace — замена в заданной строке sx символов, перечисленных в unchars (типа: множество символов), на символ char_repl;
- str_build_left — нарастить входную строку заданными символами до заданного размера слева;
- str_build_right — нарастить входную строку заданными символами до заданного размера справа.
CREATE OR REPLACE FUNCTION public.str_words_count( sx text, sunchar character varying DEFAULT ' '::character varying, yestrimbefore boolean DEFAULT true, sxrenovina character varying DEFAULT '|'::character varying) RETURNS integer AS $BODY$ DECLARE i integer; k integer; m integer; inword boolean; ch char(1); res integer; BEGIN /* Вычислить кол-во слов в строке Sx. Разделителями слов могут быть любые символы из sUnChar Параметры: sx - входная строка; sunchar - НеСимволы. Строка (типа - множество НеСимволов); yestrimbefore - если TRUE, то перед обработкой удаляются НеСимволы слева и справа в Sx sxrenovina - подстрока, на которую заменяются пробелы (следствие НеЯсности для меня работы функций substring, position). Такого символа в принципе не должно быть в строке. Возвращаемое значение: кол-во слов (integer) Примеры: select str_words_count(' ,,,1, ;;; 2, 3', ' ,'); -- 4 слова select * from str_words_count('1,2 ;3', ';, '); -- 3 слова select * from str_words_count('1,2 ;3', ','); -- 2 слова select * from str_words_count('1,2 ;3', ';3' ); -- 1 слово select * from str_words_count('1,2 ;3', ' ' ); -- 2 слова select * from str_words_count('1, 2 ;3', ' ' ); -- 3 слова select * from str_words_count('1, ;;; 2,,,, ; 3', ',;' ); -- 5 слов select * from str_words_count('1, ;;; 2,,,, ; 3', ', ;' ); -- 3 слова */ res = 0; IF (sx is NULL) THEN sx = ''; END IF; IF (sunchar is NULL) THEN sunchar = ' '; END IF; yestrimbefore = bool_is_null(yestrimbefore); IF (yestrimbefore) THEN sx = btrim(sx,sunchar); END IF; m = char_length(sx); IF (m>0) THEN IF (char_length(sunchar)>0) THEN -- ************************************** -- Это - на предмет НеЧеткости описАния и работы какой-то из функций: substring, position IF (sxrenovina is NULL) THEN sxrenovina = ''; END IF; IF char_length(sxrenovina)>0 THEN k = position(' ' in sunchar); IF k<=0 THEN sx = replace(sx,' ',sxrenovina); END IF; END IF; -- ************************************** res = 0; inword = false; i = 0; WHILE i<m LOOP i = i + 1; ch = substring(sx,i,1); k = position(ch in sunchar); IF k<=0 THEN IF (NOT inword) THEN res = res+1; END IF; inword = true; ELSE inword = false; END IF; END LOOP; ELSE res = 1; END IF; END IF; RETURN res; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; COMMENT ON FUNCTION public.str_words_count(text, character varying, boolean, character varying) IS 'Вычислить кол-во слов в строке';
CREATE OR REPLACE FUNCTION public.str_word_by_num( sx text, num integer, sunchar character varying DEFAULT ' '::character varying, yestrimbefore boolean DEFAULT true, sxrenovina character varying DEFAULT '|'::character varying) RETURNS text AS $BODY$ DECLARE i integer; k integer; m integer; nword integer; inword boolean; yesexit boolean; ch char(1); res text; BEGIN /* Получить слово из строки по его номеру. Алгоритм, мягко говоря, не быстрый Разделителями слов могут быть любые символы из sUnChar Параметры: sx - входная строка; num - номер слова в строке; sunchar - НеСимволы. Строка (типа - множество НеСимволов); yestrimbefore - если TRUE, то перед обработкой удаляются НеСимволы слева и справа в Sx; sxrenovina - символ, на который заменяются пробелы (следствие НеЯсности для меня работы функций substring, position). Такого символа в принципе не должно быть в строке. Возвращаемое значение: слово по его номеру Примеры: select str_word_by_num(' ,,,1, ;;; 2, 3', 3, ' ,'); -- 2 select * from str_word_by_num('1,2a ;3', 2, ';, '); -- 2a select * from str_word_by_num('1,2 ;3', 2, ','); -- 2 ;3 select * from str_word_by_num('1,2 ;3', 2, ';3' ); -- пустая строка select * from str_word_by_num('1,2 ;3', 2, ' ' ); -- ;3 select * from str_word_by_num('1, 2 ;3', 2, ' ' ); -- 2 */ res = ''; IF (sx is NULL) THEN sx = ''; END IF; IF (sunchar is NULL) THEN sunchar = ' '; END IF; yestrimbefore = bool_is_null(yestrimbefore); IF (yestrimbefore) THEN sx = btrim(sx,sunchar); END IF; m = char_length(sx); IF (m>0) THEN IF (char_length(sunchar)>0) THEN -- ************************************** -- Это - на предмет НеЧеткости описАния и работы какой-то из функций: substring, position IF (sxrenovina is NULL) THEN sxrenovina = ''; END IF; IF char_length(sxrenovina)>0 THEN k = position(' ' in sunchar); IF k<=0 THEN sx = replace(sx,' ',sxrenovina); END IF; END IF; -- ************************************** yesexit = false; nword = 0; inword = false; i = 0; WHILE i<m LOOP i = i + 1; IF (not yesexit) THEN ch = substring(sx,i,1); k = position(ch in sunchar); IF k<=0 THEN IF (NOT inword) THEN nword = nword+1; END IF; inword = true; ELSE inword = false; IF (nword>=num) THEN yesexit = true; -- Выход из цикла END IF; END IF; IF (inword) THEN IF (nword=num) THEN res = res || ch; END IF; END IF; END IF; END LOOP; res = replace(res, sxrenovina, ' '); ELSE res = sx; END IF; END IF; IF (res is NULL) THEN res = ''; END IF; RETURN res; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; COMMENT ON FUNCTION public.str_word_by_num(text, integer, character varying, boolean, character varying) IS 'Получить слово из строки по его номеру';
CREATE OR REPLACE FUNCTION public.str_sets_intersect( set1 text, set2 text, sep_left character DEFAULT '['::bpchar, sep_right character DEFAULT ']'::bpchar, yes_upper boolean DEFAULT true, sxrenovina character DEFAULT '`'::bpchar) RETURNS boolean AS $BODY$ DECLARE i integer; c integer; sxrenovina char; s character varying; res boolean; BEGIN /* Проверка пересечения 2-х множеств, заданных в виде строк символов Параметры: set1 - множество 1; set2 - множество 2; sep_left - разделитель элементов множества слева; sep_right - разделитель элементов множества справа; yes_upper - игнорировать регистр символов. Важно! 1. Очевидно, что элементы множества НЕ должны содержать разделителей; 2. Полное равенство строк (set1 и set2) считается пересечением (включая и пустые строки). 3. Символ sxrenovina НЕ должен присутствовать среди символов в: set1, set2, sep_left, sep_right Возвращаемое значение: TRUE, если множества пересекаются. FALSE в противном случае Примеры: select * from str_sets_intersect('[1][3679][3680]', '[3680]'); -- true select * from str_sets_intersect('[1][3679][3680]', '[3680][100]'); -- true select * from str_sets_intersect('[1][3679][3680]', '[3681][100]'); -- false select * from str_sets_intersect('[1]', '[3680]'); -- false select * from str_sets_intersect('[1]', '[1][3680]'); -- true select * from str_sets_intersect('[ 1]', '[1][3680]'); -- false select * from str_sets_intersect('[1]' || chr(10) || '[3679]' || chr(10) || '[3680]', '[15][3680]'); -- true select * from str_sets_intersect('[1]' || chr(10) || '[3679]' || chr(10) || chr(13) || chr(9) || '[3680]', '[15]' || chr(10) || '[3685]' || chr(10) || '[3679]'); -- true */ res = false; set1 = str_is_null(set1); set2 = str_is_null(set2); yes_upper = bool_is_null(yes_upper); IF (yes_upper = TRUE) THEN set1 = upper(set1); set2 = upper(set2); END IF; IF (set1 = set2) THEN res = true; ELSE IF (sep_left is null) THEN sep_left = '['; END IF; IF (sep_right is null) THEN sep_right = ']'; END IF; IF (sxrenovina is null) THEN sxrenovina = '`'; END IF; c = str_words_count(set1, sep_left || sep_right, false, sxrenovina); IF (c>0) THEN i = 0; WHILE i<c LOOP i = i + 1; s = str_word_by_num(set1, i, sep_left || sep_right, false, sxrenovina); IF (s <> '') THEN s = sep_left || s || sep_right; IF (position(s in set2)>0) THEN res = true; i = c+1; END IF; END IF; END LOOP; END IF; END IF; RETURN Res; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; COMMENT ON FUNCTION public.str_sets_intersect(text, text, character, character, boolean, character) IS 'Проверка пересечения 2-х множеств, заданных в виде строк символов';
1CREATE OR REPLACE FUNCTION public.str_reverse(sx character varying) RETURNS character varying AS $BODY$ DECLARE res character varying; BEGIN /* Инвертирвать строку sx Пример: select * from str_reverse(null); select * from str_reverse('Привет, как дела ?'); select * from str_reverse(str_reverse('Привет, как дела ?')); select * from str_reverse(' Привет, как дела ?'); select * from str_reverse(' Привет, как дела ? '); select * from str_reverse(str_reverse(' Привет, как дела ? ')); */ sx = str_is_null(sx,'',false); res = reverse(sx); RETURN res; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; COMMENT ON FUNCTION public.str_reverse(character varying) IS 'Инвертирвать строку sx';
CREATE OR REPLACE FUNCTION public.str_replace( sx character varying, unchars character varying DEFAULT ' '::character varying, char_repl character DEFAULT '_'::bpchar, char_xz character DEFAULT '|'::bpchar) RETURNS character varying AS $BODY$ DECLARE i integer; yes99 boolean; m integer; k integer; ch char(1); res character varying; BEGIN /* Замена в строке sx символов, перечисленных в unchars (типа: множество символов), на символ char_repl Вх. параметры: sx - входная строка; unchars - перечень НеСимволов (аналог множества символов); char_repl - замещающий символ; char_xz - символ, "компенсирующий" пробел в unchars. ВАЖНО!!! Среди символов unchars не должно быть символа char_xz и, кроме этого, нельзя, чтобы char_xz = ' '. Пример: select * from str_replace('Привет, как дела ?', ' ,?', '_'); -- Привет__как_дела__ select * from str_replace('Привет, как дела ? | А у тебя?', '| ,?', '_'); -- Привет__как_дела___|_А_у_тебя_ select * from str_replace('Привет, как дела ? | А у тебя?', '| ,?', '_', '\'); -- Привет__как_дела_____А_у_тебя_ select * from str_replace(btrim(' Привет, как дела ? | А у тебя?' ), '| ,?', '_', '\'); -- Привет__как_дела_____А_у_тебя_ */ res = ''; IF (sx is NULL) THEN sx = ''; END IF; IF (sx <> '') THEN res = sx; IF (unchars is NULL) THEN unchars = ''; END IF; m = char_length(unchars); IF (m>0) THEN IF (char_xz is NULL) THEN char_xz = '|'; END IF; unchars = replace(unchars,' ',char_xz); IF (char_repl is NULL) THEN char_repl = '_'; END IF; i = 0; WHILE i<m LOOP i = i + 1; ch = substring(unchars,i,1); IF (ch = char_xz) THEN res = replace(res, ' ', char_repl); ELSE res = replace(res, ch, char_repl); END IF; END LOOP; END IF; END IF; RETURN res; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; COMMENT ON FUNCTION public.str_replace(character varying, character varying, character, character) IS 'Замена в строке sx символов, перечисленных в unchars (типа: множество символов), на символ char_repl';
CREATE OR REPLACE FUNCTION public.str_build_left( sx text, newsize integer, ch character DEFAULT '0'::bpchar) RETURNS text AS $BODY$ DECLARE res text; yes99 boolean; BEGIN /* Нарастить входную строку заданными символами до заданного размера слева sx - входня строка newsize - новый размер строки ch - символы, которыми "наращивается строка" Пример вызова: select str_build_left ('3',5,'0'); -- Результат: 00003 select str_build_left ('3',10,'-'); -- Результат: ---------3 select str_build_left ('Привет',10,'='); -- Результат: ====Привет select str_build_left ('',10,' '); */ sx = str_is_null(sx); res = sx; newsize = int_is_null(newsize); IF (newsize > 0) THEN yes99 = false; IF (ch IS NULL) THEN ch =' '; END IF; IF (ch = ' ') THEN ch = '|'; yes99 = true; END IF; WHILE (CHAR_LENGTH(res) < newsize) LOOP res = ch || res; END LOOP; IF (yes99 = true) THEN res = replace(res,'|',' '); END IF; END IF; res = str_is_null(res,'',false); RETURN res; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; COMMENT ON FUNCTION public.str_build_left(text, integer, character) IS 'Нарастить входную строку заданными символами до заданного размера слева';
CREATE OR REPLACE FUNCTION public.str_build_right( sx text, newsize integer, ch character DEFAULT '0'::bpchar) RETURNS text AS $BODY$ DECLARE res text; yes99 boolean; BEGIN /* Нарастить входную строку заданными символами до заданного размера справа sx - входная строка newsize - новый размер строки ch - символы, которыми "наращивается строка" Пример вызова: select str_build_right ('3',5,'0'); Результат: 30000 */ sx = str_is_null(sx); res = sx; newsize = int_is_null(newsize); IF (newsize > 0) THEN IF (ch IS NULL) then ch =' '; END IF; IF (ch = ' ') THEN ch = '|'; yes99 = true; END IF; WHILE (CHAR_LENGTH(res) < newsize) LOOP res = res || ch; END LOOP; IF (yes99 = true) THEN res = replace(res,'|',' '); END IF; END IF; res = str_is_null(res); RETURN res; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; COMMENT ON FUNCTION public.str_build_right(text, integer, character) IS 'Нарастить входную строку заданными символами до заданного размера справа';
Скачать PG-backup (SQL-текст функций)
Продолжение следует…
Дата: 07.12.2021