powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Склонение фамилий. (Вариант решения)
25 сообщений из 40, страница 1 из 2
Склонение фамилий. (Вариант решения)
    #33666329
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно хотелось бы поделиться сабжем. На форуме я других версий не нашел, поэтому решил выложить то чем у нас пользуются для склонения фамилий. Может будут придложения и замечания.
ЗЫ Я не автор.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
CREATE OR REPLACE PACKAGE PADEG_PACK
  IS

function GetFIOPadeg(sFIO in VarChar2, NumPadeg in BINARY_INTEGER) return VarChar2;
  function str_Left(word varchar2, n number) return varchar2;
  function str_Right(word varchar2, n number) return varchar2;
  function IIF(bool boolean, str1 varchar2, str2 varchar2) return varchar2;
  function IIF(bool boolean, num1 number, num2 number) return number;
  function Get_F_I_O(str varchar2, num number ) return varchar2;
  FUNCTION GET_SEX (pO IN VarChar2)
   RETURN VarChar2;
  function Padeg_FIO(fio varchar2, p_Padeg varchar2) return varchar2;
  function Padeg_Word(p_Word varchar2, p_Padeg varchar2, p_Sex varchar2, p_SurnameFlag number, p_DontInflect number) return varchar2;
END; -- Package spec

/
CREATE OR REPLACE PACKAGE BODY PADEG_PACK
IS

------------------------------------------------------------------------------
-- Падежи:
-- Именительный - кто?что? (это)
-- Родительный - кого?чего? (нет)
-- Дательный - кому?чему? (дать)
-- Винительный - кого?что? (вижу)
-- Творительный - кем?чем? (доволен)
-- Предложный - о ком?о чём? (говорю)
-- Падеж задается первой буквой своего названия: "и", "р", "д", "в", "т", "п"
------------------------------------------------------------------------------

------------------------------------------------------------------------
-- function GetFIOPadeg(sFIO in VarChar2, NumPadeg in BINARY_INTEGER) return VarChar2
-- возвращает склонение фамилии в нужном падеже
function GetFIOPadeg(sFIO in VarChar2, NumPadeg in BINARY_INTEGER) return VarChar2
-----------------------
-- Входящие параметры:
-- -------------------------------------------------------------------------------------------
-- Имя            Смысл                                 Значение
-- -------------------------------------------------------------------------------------------
-- sFIO      - Фамилия Имя Отчество
-- NumPadeg  - падеж, в который нужно просклонять ФИО -  "Р" 2, "Д" 3, "В" 4, "Т" 5, "П" 6
-- -------------------------------------------------------------------------------------------
is
  RFIO VarChar2( 550 );
  S VarChar2( 550 );
  I BINARY_INTEGER;
  J Number;
begin
  RFIO := sFIO;
  S := 'ИРДВТП';
  s := substr(s, NumPadeg,  1 );
  return Padeg_FIO(RFIO, s);
end;

-----------------------------------------------------------------------------
-- Пример Использования.
/*
       <ФИО>                     padeg_pack.getfiopadeg(<ФИО>,2)   или  padeg_pack.padeg_fio(<ФИО>,'Р')
       -----                                -----                           -----
Бухонова Галина Петровна        	Бухоновой Галины Петровны        	Бухоновой Галины Петровны
Тикунов Владимир Петрович       	Тикунова Владимира Петровича     	Тикунова Владимира Петровича
Бойкова Елена Васильевна        	Бойковой Елены Васильевны        	Бойковой Елены Васильевны
Бойков Иван Александрович       	Бойкова Ивана Александровича     	Бойкова Ивана Александровича
Перевозчикова Любовь Викторовна 	Перевозчиковой Любови Викторовны 	Перевозчиковой Любови Викторовны
Мязин Владимир Дмитриевич       	Мязин Владимира Дмитриевича      	Мязин Владимира Дмитриевича
Матвеев Вячеслав Михайлович     	Матвеева Вячеслава Михайловича   	Матвеева Вячеслава Михайловича
*/



------------------------------------------------------------------------
-- function Padeg_FIO(fio varchar2, p_Padeg varchar2) return varchar2
-- возвращает склонение фамилии в нужном падеже
function Padeg_FIO(fio varchar2, p_Padeg varchar2) return varchar2
-----------------------
-- Входящие параметры:
-- ----------------------------------------------------------------------------
-- Имя            Смысл                                 Значение
-- ----------------------------------------------------------------------------
-- fio      - Фамилия Имя Отчество
-- p_Padeg  - падеж, в который нужно просклонять ФИО -  "Р", "Д", "В", "Т", "П"
-- ----------------------------------------------------------------------------
is
    surname     varchar2( 2000 );
    first_name  varchar2( 2000 );
    second_name varchar2( 2000 );
    v_endFIO    varchar2( 2000 );
    v_Sex       varchar2( 2000 );
    v_DontInflect number;
begin
	v_endFIO := fio;
	
	surname := Get_F_I_O(v_endFIO,  1 );
	first_name := Get_F_I_O(v_endFIO,  2 );
	second_name := Get_F_I_O(v_endFIO,  3 );

    v_Sex := GET_SEX(second_name);
	v_DontInflect :=  iif (v_Sex='', 1 , 0 );
	v_endFIO :=
	       Padeg_Word(surname,p_Padeg,v_Sex, 1 ,v_DontInflect) || ' ' ||
           Padeg_Word(first_name,p_Padeg,v_Sex, 0 ,v_DontInflect) || ' ' ||
           Padeg_Word(second_name,p_Padeg,v_Sex, 0 ,v_DontInflect);

    return v_endFIO;

end;


--------------------------------------------------------------------------------
-- Get_F_I_O - возращает одну из частей ФИО, в зависимости от параметра num.
-- 1 - Фамилия
-- 2 - Имя
-- 3 - Отчество и все осталное.
-- 4 - Фамилия И. О.
-- 5 - И. О. Фамилия
-- 6 - Имя Отчество Фамилия
function Get_F_I_O(str varchar2, num number ) return varchar2
as
-- type T_F_I_O is VArray(3) of varchar2(255)
    res T_F_I_O := T_F_I_O();
    first_name  varchar2( 60 );
    second_name varchar2( 60 );
    surname     varchar2( 60 );
    str1 varchar2( 1021 );
    str2 varchar2( 1021 );
    str3 varchar2( 1021 );
    i number;
    j number;

begin

   if (str is null) or ( length(str) >=  55 ) then
      return str;
   end if;

   str1 := str;
   j :=  1 ;
   res := T_F_I_O('','','');
 loop
   str2 := trim(str1);
   i := instr(str2, ' ');
--   res.extend;
   if i =  0  or j =  3  then
      res(j) := str1;
   else
      res(j) := substr(str2,  1 , i);
      str1 := trim(substr(str2, i));
   end if;
   exit when i =  0  or j =  3 ;
   j := j +  1 ;
 end loop;

   surname     := res( 1 );
   first_name  := res( 2 );
   second_name := res( 3 );

   res.DELETE;
   res := null;

   return case
       when num =  1  then surname
       when num =  2  then first_name
       when num =  3  then second_name
       when num =  4  then INITCAP(surname)||' '||Upper(Substr(first_name, 1 , 1 ))||'. '||Upper(Substr(second_name, 1 , 1 ))||'. '
       when num =  5  then Upper(Substr(first_name, 1 , 1 ))||'. '||Upper(Substr(second_name, 1 , 1 ))||'. '||INITCAP(surname)
       when num =  6  then first_name||' '||second_name||' '||surname
       else '' --res(1)||res(2)||res(3)
   end;
end;


-----------------------------------------------------------------------
-- GET_SEX - возвращает начальную букву пола М/Ж, если пол определен
--           или пустую строку.
-- входной параметр - Отчество
-- Добавил Коробков Георгий 24.11.05
FUNCTION GET_SEX (pO IN VarChar2)
   RETURN VarChar2
IS
   S     VarChar2 ( 256 );
   Res   CHAR;
BEGIN
   Res := lower (Substr (pO, Length (pO)));

   if Res = 'ч'
   then
      RETURN 'М';
   end if;

   if Res = 'а'
   then
      RETURN 'Ж';
   end if;

   RETURN '';
EXCEPTION
   WHEN OTHERS
   THEN
      return Null;
END;



--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-
-- Главная функция склонения !!!
-- function Padeg_Word возвращает обработанную строку в нужном падеже
function Padeg_Word(p_Word varchar2, p_Padeg varchar2, p_Sex varchar2, p_SurnameFlag number, p_DontInflect number) return varchar2
is
-- Входящие параметры:
-- -------------------------------------------------------------------------------------------
-- Имя      Смысл                                        Значение
-- -------------------------------------------------------------------------------------------
-- p_Word   - слово, которое нужно просклонять
-- p_Padeg  - падеж, в который нужно просклонять p_Word  - "Р", "Д", "В", "Т", "П"
-- p_Sex    - пол p_Word                                 - "М" / <не "М">
-- p_SurnameFlag  - p_Word - это фамилия ?               -  НЕпустое значение / пустое значение
-- p_DontInflect  - определенно не склонять p_Word       -  НЕпустое значение / пустое значение
-- -------------------------------------------------------------------------------------------
--
	        v_SS          varchar2( 2000 );
            v_RWord1      varchar2( 2000 );
            v_RWord2      varchar2( 2000 );
            v_RWord3      varchar2( 2000 );
            v_Padeg       varchar2( 2000 );
            v_DontInflect varchar2( 2000 );
            v_UpCase      varchar2( 2000 );
            v_DlSS        varchar2( 2000 );
            v_IsSurname   varchar2( 2000 );
begin
	v_SS := trim(p_Word);
	v_Padeg := Upper( str_Left(p_Padeg,  1 ) );
	v_Padeg :=  case when  instr('РДВТП',v_Padeg)> 0  then v_Padeg else 'И' end;
	v_IsSurname   :=  case when  nvl(p_SurnameFlag,  0 ) =  0  then  0  else  1  end;
	v_DontInflect :=  case when  nvl(p_DontInflect,  0 ) =  0  then  0  else  1  end;
	if v_DontInflect =  1  then   -- Слово несклоняемое - выходим
		return v_SS;
	end if;
	if v_Padeg = 'И' then  -- Именительный падеж - нечего менять
		return v_SS;
	end if;
	v_RWord1  := str_Right(v_SS, 1 ); 
	v_UpCase :=  case when ASCII(v_RWord1)>= 192  and ASCII(v_RWord1)<= 223  then   1  else  0  end;
	v_DlSS    := length(v_SS);
	v_RWord1  := Upper(str_Right(v_SS, 1 ));

	v_RWord2  := Upper(Substr(v_SS,v_DlSS -  1 , 1 ));
	v_RWord3  := Upper(Substr(v_SS,v_DlSS -  2 , 1 ));
	-- Обработка нестандартных слов
	if Upper(v_SS) = 'ЛЕВ' then
		v_SS :=   str_Left(v_SS, 1 ) ||  case when v_Padeg='Р' then  case when v_UpCase= 1  then 'ЬВА' else 'ьва' end
                                    else
										     case when v_Padeg='Д' then   case when v_UpCase= 1  then 'ЬВУ' else 'ьву' end
										          else
											                case when v_Padeg='В' then   case when v_UpCase= 1  then 'ЬВА' else 'ьва' end
											                     else
														                   case when v_Padeg='Т' then  case when v_UpCase= 1  then 'ЬВОМ'
                                                                                                         else 'ьвом'
                                                                                                    end
                                                                                else
																		                  case when v_Padeg='П' then  case when v_UpCase =  1  then 'ЬВЕ'
                                                                                                                           else 'ьве'
                                                                                                                      end
																						       else ''
                                                                                          end
                                                                           end
                                                              end
                                              end
                             end;
		return v_SS;
	elsif Upper(v_SS)='ПАВЕЛ' then
		v_SS := str_Left(v_SS, 3 ) ||  case when v_Padeg='Р' then   case when v_UpCase= 1  then 'ЛА' else 'ла' end
                                         else
		                                     case when v_Padeg='Д' then   case when v_UpCase= 1  then 'ЛУ' else 'лу' end
                                                  else
											                case when v_Padeg='В' then   case when v_UpCase= 1  then 'ЛА' else 'ла' end
                                                                 else
														                   case when v_Padeg='Т' then   case when v_UpCase= 1  then 'ЛОМ' else 'лом' end
														                        else
																		                  case when v_Padeg='П' then  case when v_UpCase= 1  then 'ЛЕ' else 'ле' end
																						       else      ''
                                                                                          end
                                                                            end
                                                             end
                                             end
                                     end;
		return v_SS;
	end if;
	-- Непосредственно обработка окончания
	if v_RWord1='А' then
		if v_RWord2='К' then
			v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  case when v_Padeg='Р' then   case when v_UpCase= 1  then 'И' else 'и' end
                                                    else
			                                            case when v_Padeg='Д' then  case when v_UpCase= 1  then 'Е' else 'е' end
                                                             else
													                   case when v_Padeg='В' then   case when v_UpCase= 1  then 'У' else 'у'end
                                                                            else
																	                  case when v_Padeg='Т' then  case when v_UpCase= 1  then 'ОЙ' else 'ой' end
                                                                                          else
																					                 case when v_Padeg='П' then   case when v_UpCase= 1  then 'Е' else 'е' end
                                                                                                          else      ''
                                                                                                     end
                                                                                      end
                                                                       end
                                                        end
                                               end         ;

		elsif v_RWord2='Ц' then
			v_SS := str_Left(v_SS,v_DlSS- 1 ) +  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'Ы','ы'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'Е','е'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'У','у'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЕЙ','ей'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																									               '')))));
		else
			if (v_IsSurname =  1 ) and (p_Sex = 'Ж') then
				if (v_RWord2='В') or (v_RWord2='Н') then
					v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'ОЙ','ой'),
					                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'ОЙ','ой'),
															                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'У','у'),
																			                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОЙ','ой'),
																							                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'ОЙ','ой'),
																											               '')))));
				else	
					v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'Ы','ы'),
					                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'Е','е'),
															                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'У','у'),
																			                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОЙ','ой'),
																							                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																											               '')))));
				end if;	
			else	
				v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'Ы','ы'),
				                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'Е','е'),
														                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'У','у'),
																		                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОЙ','ой'),
																						                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																										               '')))));
			end if;
		end if;
	elsif v_RWord1='Б' then
		v_SS := v_SS ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'А','а'),
		                              iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'У','у'),
									                 iif (v_Padeg='В',  iif (v_UpCase= 1 ,'А','а'),
													                iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОМ','ом'),
																                   iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																				                 '')))));
	elsif v_RWord1='В' then
		if (v_RWord2='А') or (v_IsSurname= 0 ) then
			v_SS := v_SS ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'А','а'),
			                              iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'У','у'),
										                 iif (v_Padeg='В',  iif (v_UpCase= 1 ,'А','а'),
														                iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОМ','ом'),
																	                   iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																					                 '')))));
		else
			v_SS := v_SS ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'А','а'),
			                              iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'У','у'),
										                 iif (v_Padeg='В',  iif (v_UpCase= 1 ,'А','а'),
														                iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЫМ','ым'),
																	                   iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																					                 '')))));
		end if;
	elsif (v_RWord1 = 'Г') or (v_RWord1 = 'Д') or (v_RWord1 = 'Ж') or
				(v_RWord1 = 'З') or (v_RWord1 = 'К') or (v_RWord1 = 'Л') or
				(v_RWord1 = 'М') or (v_RWord1 = 'Н') and (v_RWord2 <> 'И') and (v_RWord2 <> 'Ы') or
				(v_RWord1 = 'П') or (v_RWord1 = 'Р') or (v_RWord1 = 'С') or
				(v_RWord1 = 'Т') or (v_RWord1 = 'Ф') or
				(v_RWord1 = 'Х') and (v_RWord2 <> 'И')and (v_RWord2 <> 'Ы') or
				(v_RWord1 = 'Щ') then
		if (v_IsSurname =  1 ) and (p_Sex = 'Ж') then
			return v_SS;
		else
			v_SS := v_SS ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'А','а'),
			                              iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'У','у'),
										                 iif (v_Padeg='В',  iif (v_UpCase= 1 ,'А','а'),
														                iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОМ','ом'),
																	                   iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																					                 '')))));
		end if;	
	elsif v_RWord1 = 'Й' then
		if (v_IsSurname =  1 ) and (p_Sex = 'Ж') then
			return(v_SS);
		elsif (v_RWord2='И') and (v_RWord3='К') then
			v_SS := str_Left(v_SS,v_DlSS- 2 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'ОГО','ого'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'ОМУ','ому'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'ОГО','ого'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ИМ','им'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'ОМ','ом'),
																									               '')))));
		elsif (v_RWord2='И') and ((v_RWord3='Ш') and (v_RWord3='Щ')) then
			v_SS := str_Left(v_SS,v_DlSS- 2 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'ЕГО','его'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'ЕМУ','ему'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'ЕГО','его'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ИМ','им'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'ЕМ','ем'),
																									               '')))));
		elsif (v_RWord2='О') or (v_RWord2='Ы') then
			v_SS := str_Left(v_SS,v_DlSS- 2 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'ОГО','ого'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'ОМУ','ому'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'ОГО','ого'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЫМ','ым'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'ОМ','ом'),
																									               '')))));
		elsif (v_RWord2='А') or (v_RWord2='Е') or (v_RWord2='И') or (v_RWord2='У') or (v_RWord2='Э') or (v_RWord2='Ю')
				or (v_RWord2='Я') and (v_RWord3<>'К') then
			v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'Я','я'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'Ю','ю'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'Я','я'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЕМ','ем'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																									               '')))));
		end if;
	elsif (v_RWord1 = 'Н') and ((v_RWord2 = 'И') and (v_RWord2 = 'Ы')) then
		if v_IsSurname= 1  then
			v_SS := v_SS ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'А','а'),
			                              iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'У','у'),
										                 iif (v_Padeg='В',  iif (v_UpCase= 1 ,'А','а'),
														                iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЫМ','ым'),
																	                   iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																					                 '')))));
		else
			v_SS := v_SS ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'А','а'),
			                              iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'У','у'),
										                 iif (v_Padeg='В',  iif (v_UpCase= 1 ,'А','а'),
														                iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОМ','ом'),
																	                   iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																					                 '')))));
		end if;
	elsif (v_RWord1 = 'Х') and ((v_RWord2 = 'И') or (v_RWord2 = 'Ы')) then
   	    --return v_SS;
   	    null;
		-- НЕ СКЛОНЯЮТСЯ
	elsif (v_RWord1 = 'Ц') or (v_RWord1 = 'Ч') or (v_RWord1 = 'Ш') then
		if (v_IsSurname =  1 ) and (p_Sex = 'Ж') then
			return v_SS;
		else
			v_SS := v_SS || iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'А','а'),
			                              iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'У','у'),
										                 iif (v_Padeg='В',  iif (v_UpCase= 1 ,'А','а'),
														                iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЕМ','ем'),
																	                   iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																					                 '')))));
		end if;
	elsif v_RWord1 = 'Ь' then
		if p_Sex = 'М' then
			v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'Я','я'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'Ю','ю'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'Я','я'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЕМ','ем'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																									               '')))));
		else
			if v_IsSurname =  1  then
				v_SS := v_SS;
			else
				v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'И','и'),
				                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'И','и'),
														                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'Ь','ь'),
																		                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЬЮ','ью'),
																						                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'И','и'),
																										               '')))));
			end if;
		end if;
	elsif v_RWord1 = 'Я' then
		if v_RWord2 = 'М' then
			v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'ЕНИ','ени'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'ЕНИ','ени'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'Я','я'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЕНЕМ','енем'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'ЕНИ','ени'),
																									               '')))));
		elsif v_RWord2 = 'И' then
			v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'И','и'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'И','и'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'Ю','ю'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЕЙ','ей'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'И','и'),
																									               '')))));
		elsif v_RWord2 = 'А' then
			v_SS := str_Left(v_SS,v_DlSS- 2 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'ОЙ','ой'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'ОЙ','ой'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'УЮ','ую'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ОЙ','ой'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'ОЙ','ой'),
																									               '')))));
		else	
			v_SS := str_Left(v_SS,v_DlSS- 1 ) ||  iif (v_Padeg='Р',  iif (v_UpCase= 1 ,'И','и'),
			                                            iif (v_Padeg='Д',  iif (v_UpCase= 1 ,'Е','е'),
													                   iif (v_Padeg='В',  iif (v_UpCase= 1 ,'Ю','ю'),
																	                  iif (v_Padeg='Т',  iif (v_UpCase= 1 ,'ЕЙ','ей'),
																					                 iif (v_Padeg='П',  iif (v_UpCase= 1 ,'Е','е'),
																									               '')))));
		end if;
	end if;

	return v_SS;
end;

----------------------------------------------------------------
-- Вспомгательные функции
--------------------------

function str_Left(word varchar2, n number) return varchar2
is
begin
   return substr(word,  0 , n);
end;

function str_Right(word varchar2, n number) return varchar2
is
begin
   return substr(word, length(word) +  1  - n );
end;

function IIF(bool boolean, str1 varchar2, str2 varchar2) return varchar2
is
begin
   return case when bool then str1 else str2 end;
end;

function IIF(bool boolean, num1 number, num2 number) return number
is
begin
   return case when bool then num1 else num2 end;
end;


END;


...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666333
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Буду рад увидеть другие варианты.
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666338
Бомж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
аффтар
function IIF(bool boolean, str1 varchar2, str2 varchar2) return varchar2
is
begin
return case when bool then str1 else str2 end;
end;

function IIF(bool boolean, num1 number, num2 number) return number
is
begin
return case when bool then num1 else num2 end;
end;


Decode?

© Бомж Inc.
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666477
я
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
я
Гость
geo_lifeБуду рад увидеть другие варианты.Ты лучше для этого варианта выложи недостающие детали. А то он там без типа компилится не хочет...
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666514
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бомж аффтарfunction IIF(bool boolean, str1 varchar2, str2 varchar2) return varchar2
return case when bool then str1 else str2 end;
Decode?
STFF в PL/SQL-е нет decode
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666524
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бомж аффтар
function IIF(bool boolean, str1 varchar2, str2 varchar2) return varchar2
is
begin
return case when bool then str1 else str2 end;
end;

function IIF(bool boolean, num1 number, num2 number) return number
is
begin
return case when bool then num1 else num2 end;
end;


Decode?

© Бомж Inc.
Если быть точнее
Код: plaintext
CASE WHEN <bool> THEN <str1> ELSE <str2> END;
в DECODE нельзя писать логическое условие.
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666537
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
CREATE OR REPLACE TYPE T_F_I_O
 AS VARYING ARRAY ( 3 ) OF VARCHAR2( 255 )
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666553
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CREATE OR REPLACE 
PACKAGE padeg_pack
  IS

function GetFIOPadeg(sFIO in VarChar2, NumPadeg in BINARY_INTEGER) return VarChar2;
-- !!!!!!!!!!!!!!!!!! Забыл сразу написать :)
  TYPE T_F_I_O IS VARYING ARRAY ( 3 ) OF VARCHAR2( 255 );

  function str_Left(word varchar2, n number) return varchar2;
  function str_Right(word varchar2, n number) return varchar2;
  function IIF(bool boolean, str1 varchar2, str2 varchar2) return varchar2;
  function IIF(bool boolean, num1 number, num2 number) return number;
  function Get_F_I_O(str varchar2, num number ) return varchar2;
  FUNCTION GET_SEX (pO IN VarChar2)
   RETURN VarChar2;
  function Padeg_FIO(fio varchar2, p_Padeg varchar2) return varchar2;
  function Padeg_Word(p_Word varchar2, p_Padeg varchar2, p_Sex varchar2, p_SurnameFlag number, p_DontInflect number) return varchar2;
END; -- Package spec
/
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666579
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
geo_life-- !!!!!!!!!!!!!!!!!! Забыл сразу написать :)
TYPE T_F_I_O IS VARYING ARRAY (3) OF VARCHAR2(255);

Вообще достаточно раскомментировать соответствующую строку в теле пакета :)

Но просто здорово. Титанический труд.
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666584
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
geo_lifeЕсли быть точнее: в DECODE нельзя писать логическое условие.Ещё один. В нём вообще нельзя ничего писать, потому что его там нет
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666599
Я
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Я
Гость
Благополучно коверкаются корейские фамилии, такие как Ян, Тян, Пак.
А кроме корейцев есть ещё много национальностей, где фамилии отличаются от стандартов русских. Хоть немецкие взять, к примеру. Про азиатов вообще молчу (вот у меня в базе есть такая интересное фамилиё Оглы Бирза, я даже не знаю, кто это Он или Она...).
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666633
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А у кого нибудь есть другие варианты?
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666654
Фотография dmidek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я
А кроме корейцев есть ещё много национальностей, где фамилии отличаются от стандартов русских. Хоть немецкие взять, к примеру.

Почеиу ?
Немецкие фамилии в немецком языке действительно не склоняются, но в русском склоняются нормально.
"Все рады мудрому решению канцлера Шредера" :-)
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666667
Фотография Andrew IF
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЯБлагополучно коверкаются корейские фамилии, такие как Ян, Тян, Пак.
А кроме корейцев есть ещё много национальностей, где фамилии отличаются от стандартов русских. Хоть немецкие взять, к примеру. Про азиатов вообще молчу (вот у меня в базе есть такая интересное фамилиё Оглы Бирза, я даже не знаю, кто это Он или Она...).


Фиг с ними с корейцами! Банальные русские фимилии не склоняются

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SQL> select PADEG_PACK.GetFIOPadeg('ПУТИН ВЛАДИМИР ВЛАДИМИРОВИЧ',rownum) FIO from user_objects
   2    where rownum< 7 ;


FIO                   
--------------------------------------------------------------------------------
ПУТИН ВЛАДИМИР ВЛАДИМИРОВИЧ
ПУТИН ВЛАДИМИРА ВЛАДИМИРОВИЧА
ПУТИН ВЛАДИМИРУ ВЛАДИМИРОВИЧУ
ПУТИН ВЛАДИМИРА ВЛАДИМИРОВИЧА
ПУТИН ВЛАДИМИРОМ ВЛАДИМИРОВИЧЕМ
ПУТИН ВЛАДИМИРЕ ВЛАДИМИРОВИЧЕ                                                  

 6  rows selected.

SQL> spool off
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666693
parus_func
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
create or replace function F_GETWORD_ON_CASE
(
  sSLOVO            in varchar2,        -- исходное слово, при выходе - нужный падеж
  sPADEG            in varchar2,        -- падеж (и,р,д,в,т,п)
  nPOL              in number,          -- род (1-мужской, 2-женский)
  sPR               in varchar2         -- признак (ф-фамилия, и-имя, о-отчество)
)
return varchar2
is
  tmp_sSLOVO        varchar2( 80 );
  tmp_sIM           varchar2( 80 );
  tmp_sROD          varchar2( 80 );
  tmp_sDAT          varchar2( 80 );
  tmp_sVIN          varchar2( 80 );
  tmp_sTVO          varchar2( 80 );
  tmp_sPRE          varchar2( 80 );
  tmp_sPADEG        char( 1 );
  tmp_nPOL          number;
  tmp_sPR           char( 1 );
  type t_ARR1       is varray( 5 ) of varchar2( 80 );
  type t_ARR2       is varray( 30 ) of varchar2( 80 );
  tmp_tT            t_ARR1 := t_ARR1();
  tmp_tB            t_ARR1 := t_ARR1();
  tmp_tPAD          t_ARR2 := t_ARR2();
  tmp_nI            number;
  tmp_nJ            number;
  tmp_nLN           number;
begin
  /* инициализация массива */
  for i in  1 .. 30 
  loop
    if i <  6  then
      tmp_tT.EXTEND;
      tmp_tB.EXTEND;
      tmp_tT(i) := '';
      tmp_tB(i) := '';
    end if;
    tmp_tPAD.EXTEND;
    tmp_tPAD(i) := '';
  end loop;
  /* Разбор параметров */
  tmp_sSLOVO := trim(sSLOVO);
  if tmp_sSLOVO is null then
    return '';
  end if;
  tmp_sPADEG := lower(substr(trim(sPADEG), 1 , 1 ));
  if (tmp_sPADEG is null) or (not tmp_sPADEG in ('и','р','д','в','т','п')) then
    tmp_sPADEG := 'и';
  end if;
  tmp_nPOL := nPOL;
  if (tmp_nPOL is null) or (not tmp_nPOL in ( 1 ,  2 )) then
    tmp_nPOL :=  1 ;
  end if;
  tmp_sPR := lower(substr(trim(sPR), 1 , 1 ));
  if (tmp_sPR is null) or (not tmp_sPR in ('ф','и','о')) then
    tmp_sPR := 'ф';
  end if;
  tmp_sIM := lower(tmp_sSLOVO);
  tmp_sROD := '';
  tmp_sDAT := '';
  tmp_sVIN := '';
  tmp_sTVO := '';
  tmp_sPRE := '';
  tmp_nLN  := length(tmp_sIM);                            -- длина слова
  tmp_nI   := tmp_nLN;
  tmp_nJ   :=  5 ;
  while (tmp_nI >  0 ) and (tmp_nJ >  0 ) loop
    -- последние пять букв
    tmp_tB(tmp_nJ) := substr(tmp_sIM, tmp_nI,  1 );
    -- признак гласной буквы
    if tmp_tB(tmp_nJ) in ('е','и','о','у','ы','а','э','ю','я') then
      tmp_tT(tmp_nJ) := 'г';
    else
      tmp_tT(tmp_nJ) := 'с';
    end if;
    tmp_nI := tmp_nI -  1 ;
    tmp_nJ := tmp_nJ -  1 ;
  end loop;
  if tmp_nPOL =  1  then
    /* таблица окончаний для МУЖСКОГО РОДА */
    tmp_tPAD( 01 ) := 'я    ю    я    ем   е    ';          --  паскал Ь
    tmp_tPAD( 02 ) := 'ы    е    ы    ой   е    ';          --  учав А
    tmp_tPAD( 03 ) := 'ю    и    и    ей   и    ';          --  хурдИ Я
    tmp_tPAD( 04 ) := 'ю    е    и    ей   е    ';          --  кана Я
    tmp_tPAD( 05 ) := 'ого  ому  ого  им   ом   ';          --  хуторецК ИЙ, островерХ ИЙ
    tmp_tPAD( 06 ) := 'его  ему  его  им   ем   ';          --  вехН ИЙ, злюЩ ИЙ. пороШ ИЙ
    tmp_tPAD( 07 ) := 'ого  ому  ого  ым   ом   ';          --  зорев ОЙ, колодн ЫЙ
    tmp_tPAD( 08 ) := 'я    ю    я    ем   е    ';          --  каравА Й
    tmp_tPAD( 09 ) := 'ка   ку   ка   ком  ке   ';          --  казан ОК
    tmp_tPAD( 10 ) := 'ьца  ьцу  ьца  ьцом ьце  ';          --  гоЛ ЕЦ
    tmp_tPAD( 11 ) := 'йца  йцу  йца  йцем йце  ';          --  коломИ ЕЦ
    tmp_tPAD( 12 ) := 'а    у    а    ом   е    ';          --  моКРЕЦ
    tmp_tPAD( 13 ) := 'ца   цу   ца   цем  це   ';          --  померАН ЕЦ
    tmp_tPAD( 14 ) := 'а    у    а    ом   е    ';          --  криХ,пыХ,мичУк,пин
    tmp_tPAD( 15 ) := 'а    у    а    ем   е    ';          --  стратовИЧ
    tmp_tPAD( 16 ) := 'а    у    а    ым   е    ';          --  карпачев, тимохов
    tmp_tPAD( 17 ) := 'и    е    у    ой   е    ';          --  шульГА
    tmp_tPAD( 18 ) := '                         ';          --
    tmp_tPAD( 19 ) := '                         ';          --
    tmp_tPAD( 20 ) := '                         ';          --  карпачев, тимохов
    tmp_tPAD( 21 ) := '                         ';          --
    tmp_tPAD( 22 ) := '                         ';          --
    tmp_tPAD( 23 ) := '                         ';          --
    tmp_tPAD( 24 ) := '                         ';          --
    tmp_tPAD( 25 ) := 'ья   ью   ья   ем   ье   ';          --  СОЛОВ ЕЙ
    tmp_tPAD( 26 ) := 'я    ю    я    ем   е    ';          --  ЕВГЕНИ Й, АРСЕНИ Й
    tmp_tPAD( 27 ) := 'ьва  ьву  ьва  ьвом ьве  ';          --  Л ЕВ
    tmp_tPAD( 28 ) := 'ла   лу   ла   лом  ле   ';          --  ПАВ ЕЛ
    tmp_tPAD( 29 ) := '                         ';          --
    tmp_tPAD( 30 ) := '                         ';          --
    /* исключения */
    if 'соловей' = tmp_sIM then                           -- Хуторецкий
      tmp_nI :=  4 ;                                        -- с предпоследнего символа
      tmp_nJ :=  25 ;                                       -- строка таблицы
    elsif ('евгений' = tmp_sIM) or ('арсений' = tmp_sIM) then
      tmp_nI :=  5 ;                                        -- с последнего
      tmp_nJ :=  26 ;
    elsif 'лев' = tmp_sIM then
      tmp_nI :=  4 ;                                        -- с предпоследнего
      tmp_nJ :=  27 ;
    elsif ('павел' = tmp_sIM) or ('орел' = tmp_sIM) then
      tmp_nI :=  4 ;                                        -- с предпоследнего
      tmp_nJ :=  28 ;
    elsif tmp_tB( 5 ) = 'ь' then                            -- Паскаль
      tmp_nI :=  5 ;                                        -- последний заменить
      tmp_nJ :=  1 ;
    elsif (tmp_tB( 4 )||tmp_tB( 5 ))
      in ('га', 'ка', 'ха') then                          -- Шульга
      tmp_nI :=  5 ;                                        -- последний
      tmp_nJ :=  17 ;
    elsif tmp_tB( 5 ) = 'а' then                            -- Учава
      tmp_nI :=  5 ;                                        -- последний заменить
      tmp_nJ :=  2 ;
    elsif tmp_tB( 4 )||tmp_tB( 5 ) = 'ия' then                -- Хурдия
      tmp_nI :=  5 ;                                        -- последний заменить
      tmp_nJ :=  3 ;
    elsif tmp_tB( 5 ) = 'я' then                            -- Каная
      tmp_nI :=  5 ;                                        -- последний заменить
      tmp_nJ :=  4 ;
    elsif tmp_tT( 5 ) = 'г' or ascii(tmp_tB( 5 )) <  192  then  -- остальные гласные и символы
      tmp_nI :=  0 ;                                        -- не склоняется
      tmp_nJ :=  0 ;
    elsif tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 ) = 'кий' then    -- Хуторецкий
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  5 ;
    elsif tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 ) = 'хий' then    -- Островерхий
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  5 ;
    elsif tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 ) = 'ний' then    -- Верхний
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  6 ;
    elsif tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 ) = 'щий' then    -- Злющий
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  6 ;
    elsif tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 ) = 'ший' then    -- Хороший
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  6 ;
    elsif tmp_tB( 4 )||tmp_tB( 5 ) = 'ой' then                -- Заревой
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  7 ;
    elsif tmp_tB( 4 )||tmp_tB( 5 ) = 'ый' then                -- Колодный
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  7 ;
    elsif tmp_tT( 4 ) = 'г' AND tmp_tB( 5 ) = 'й' then        -- Славий
      tmp_nI :=  5 ;                                        -- последний
      tmp_nJ :=  8 ;
    elsif tmp_tB( 4 )||tmp_tB( 5 ) = 'ок' then                -- Казанок
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  9 ;
    elsif tmp_tT( 2 )='г' AND tmp_tB( 3 )||tmp_tB( 4 )
      ||tmp_tB( 5 ) = 'лец' then                            -- Голец
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  10 ;
    elsif tmp_tT( 3 )='г' AND tmp_tB( 4 )||
      tmp_tB( 5 ) = 'ец' then                               -- Коломиец
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  11 ;
    elsif tmp_tT( 2 )||tmp_tT( 3 ) = 'сс' AND
      tmp_tB( 4 )||tmp_tB( 5 ) = 'ец' then                    -- Мокрец
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  12 ;
    elsif tmp_tT( 2 )||tmp_tT( 3 ) = 'гс' AND
      tmp_tB( 4 )||tmp_tB( 5 ) = 'ец' then                    -- Поморец
      tmp_nI :=  4 ;                                        -- предпоследний
      tmp_nJ :=  13 ;
    elsif tmp_nLN<= 4  AND tmp_tB( 4 )||
      tmp_tB( 5 ) = 'их' then                               -- Пих
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  14 ;
    elsif tmp_nLN<= 4  AND tmp_tB( 4 )||tmp_tB( 5 ) =
      'ых' then                                           -- Пых
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  14 ;
    elsif tmp_tB( 5 ) = 'к' then                            -- Мячик
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  14 ;
    elsif tmp_nLN<= 3  then                                 -- Пин
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  14 ;
    elsif tmp_tB( 4 )||tmp_tB( 5 ) = 'ич' then                -- Стратович
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  15 ;
    elsif (tmp_tB( 4 )||tmp_tB( 5 )) in ('ев', 'ов') or
      tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 ) = 'кин' then        -- Карпачев, Базаров, Пупыркин
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  16 ;
    else                                                  -- прочие
      tmp_nI :=  6 ;                                        -- после последнего
      tmp_nJ :=  14 ;
    end if;
  else
    /* таблица окончаний для ФАМИЛИЙ ЖЕНСКОГО РОДА */
    tmp_tPAD( 01 ) := 'ой   ой   ую   ой   ой   ';          --  белецк АЯ
    tmp_tPAD( 02 ) := 'ей   ей   юю   ей   ей   ';          --  зимн ЯЯ
    tmp_tPAD( 03 ) := 'ой   ой   у    ой   ой   ';          --  зуеВ А, погодиН А
    tmp_tPAD( 04 ) := '                         ';          --
    tmp_tPAD( 05 ) := '                         ';          --
    tmp_tPAD( 06 ) := '                         ';          --
    tmp_tPAD( 07 ) := '                         ';          --
    tmp_tPAD( 08 ) := '                         ';          --
    tmp_tPAD( 09 ) := 'и    е    у    ой   е    ';          --  ольГ А, собаК А, солоХ А
    tmp_tPAD( 10 ) := 'ы    е    у    ой   е    ';          --  ирин А
    tmp_tPAD( 11 ) := 'и    е    ю    ей   е    ';          --  наталь Я
    tmp_tPAD( 12 ) := 'и    и    ю    ей   и    ';          --  викторИ Я
    tmp_tPAD( 13 ) := 'и    и    ь    ью   и    ';          --  любов Ь
    tmp_tPAD( 14 ) := '                         ';          --
    tmp_tPAD( 15 ) := '                         ';          --
    if tmp_sPR = 'ф' then                                 -- ФАМИЛИЯ
      if tmp_tB( 4 )||tmp_tB( 5 ) = 'ая' then                 -- Белецкая
        tmp_nI :=  4 ;                                      -- предпоследний заменить
        tmp_nJ :=  1 ;
      elsif tmp_tB( 4 )||tmp_tB( 5 ) = 'яя' then              -- Зимняя
        tmp_nI :=  4 ;                                      -- предпоследний заменить
        tmp_nJ :=  2 ;
      elsif (tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 ))
        in ('ова', 'ева') then                            -- Зуева
        tmp_nI :=  5 ;                                      -- последний заменить
        tmp_nJ :=  3 ;
      elsif (tmp_tB( 3 )||tmp_tB( 4 )||tmp_tB( 5 )) in
        ('ина', 'ына') then                               -- Погодина, Брусницына
        tmp_nI :=  5 ;                                      -- последний заменить
        tmp_nJ :=  3 ;
      elsif (tmp_tB( 4 )||tmp_tB( 5 )) in
        ('га', 'ка', 'ха') then                           -- Шульга, Собака, Солоха
        tmp_nI :=  5 ;                                      -- последний заменить
        tmp_nJ :=  9 ;
      elsif tmp_tB( 5 ) = 'а' then                          -- Коляда
        tmp_nI :=  5 ;                                      -- последний заменить
        tmp_nJ :=  10 ;
      else                                                -- прочии не склонять
        tmp_nI :=  0 ;
        tmp_nJ :=  0 ;
      end if;
    else                                                  -- ИМЕНА, ОТЧЕСТВА
      if (tmp_tB( 4 )||tmp_tB( 5 ))
        in ('га', 'ка', 'ха') then                        -- Ольга, Собака, Солоха
        tmp_nI :=  5 ;                                      -- последний заменить
        tmp_nJ :=  9 ;
      elsif tmp_tB( 5 ) = 'а' then                          -- Ирина, Ивановна
        tmp_nI :=  5 ;                                      -- последний
        tmp_nJ :=  10 ;
      elsif (tmp_tB( 4 )||tmp_tB( 5 )) = 'ия' then            -- Виктория
        tmp_nI :=  5 ;                                      -- предпоследний
        tmp_nJ :=  12 ;
      elsif tmp_tB( 5 ) = 'я' then                          -- Наталья
        tmp_nI :=  5 ;                                      -- предпоследний
        tmp_nJ :=  11 ;
      elsif tmp_tB( 5 ) = 'ь' then                          -- Любовь
        tmp_nI :=  5 ;                                      -- предпоследний
        tmp_nJ :=  13 ;
      else                                                -- прочие не склонять
        tmp_nI :=  0 ;                                      -- предпоследний
        tmp_nJ :=  0 ;
      end if;
    end if;
  end if;
  /* добавление соответствующего окончания */
  tmp_sIM := tmp_sSLOVO;                                  -- восстановить начальное слово
  if (tmp_nI >=  4 ) and (tmp_nI <=  6 ) and (tmp_nJ >=  1 ) and (tmp_nJ <=  30 ) then
    tmp_nLN   := tmp_nLN + tmp_nI -  6 ;                    -- уменьшение длины слова на отбрасываемую часть
    tmp_sROD  := trim(substr(tmp_sIM,  1 , tmp_nLN) ||
      substr(tmp_tPAD(tmp_nJ),  01 ,  5 ));                   -- родительный
    tmp_sDAT  := trim(substr(tmp_sIM,  1 , tmp_nLN) ||
      substr(tmp_tPAD(tmp_nJ),  06 ,  5 ));                   -- дательный
    tmp_sVIN  := trim(substr(tmp_sIM,  1 , tmp_nLN) ||
      substr(tmp_tPAD(tmp_nJ),  11 ,  5 ));                   -- винительный
    tmp_sTVO  := trim(substr(tmp_sIM,  1 , tmp_nLN) ||
      substr(tmp_tPAD(tmp_nJ),  16 ,  5 ));                   -- творительный
    tmp_sPRE  := trim(substr(tmp_sIM,  1 , tmp_nLN) ||
      substr(tmp_tPAD(tmp_nJ),  21 ,  5 ));                   -- предложный
  else
    tmp_sROD := tmp_sIM;
    tmp_sDAT := tmp_sIM;
    tmp_sVIN := tmp_sIM;
    tmp_sTVO := tmp_sIM;
    tmp_sPRE := tmp_sIM;
  end if;
  /* нужный падеж */
  if tmp_sPadeg = 'р' then
    tmp_sSLOVO := tmp_sROD;
  elsif tmp_sPADEG = 'д' then
    tmp_sSLOVO := tmp_sDAT;
  elsif tmp_sPADEG = 'в' then
    tmp_sSLOVO := tmp_sVIN;
  elsif tmp_sPADEG = 'т' then
    tmp_sSLOVO := tmp_sTVO;
  elsif tmp_sPADEG = 'п' then
    tmp_sSLOVO := tmp_sPRE;
  end if;
  if (sSLOVO = upper(sSLOVO)) then
    return upper(tmp_sSLOVO);
  else
    return tmp_sSLOVO;
  end if;
end;
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666721
Владимор Конев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dmidek Я
А кроме корейцев есть ещё много национальностей, где фамилии отличаются от стандартов русских. Хоть немецкие взять, к примеру.

Почеиу ?
Немецкие фамилии в немецком языке действительно не склоняются, но в русском склоняются нормально.
"Все рады мудрому решению канцлера Шредера" :-)
Хорошо, а просклоняй мне, к примеру, Вальтер Инга...
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666738
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dmidek Я
А кроме корейцев есть ещё много национальностей, где фамилии отличаются от стандартов русских. Хоть немецкие взять, к примеру.
Почеиу ?
Немецкие фамилии в немецком языке действительно не склоняются, но в русском склоняются нормально.
"Все рады мудрому решению канцлера Шредера" :-)
Однако:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
SQL> select ane_padeg_pack.getfiopadeg('Римский-Корсаков Денис Владимирович',rownum) from dual connect by level <  7 ;

ANE_PADEG_PACK.GETFIOPADEG('РИ
--------------------------------------------------------------------------------
Римский-Корсаков Денис Владимирович
Римский-Корсакова Дениса Владимировича
Римский-Корсакову Денису Владимировичу
Римский-Корсакова Дениса Владимировича
Римский-Корсаковым Денисом Владимировичем
Римский-Корсакове Денисе Владимировиче

6 rows selected

SQL> select ane_padeg_pack.getfiopadeg('Лева Валерия Денисовна',rownum) from dual connect by level < 7;

ANE_PADEG_PACK.GETFIOPADEG('ЛЕ
--------------------------------------------------------------------------------
Лева Валерия Денисовна
Левой Валерии Денисовны
Левой Валерии Денисовне
Леву Валерию Денисовну
Левой Валерией Денисовной
Левой Валерии Денисовне

 6  rows selected
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666758
Фотография Tolmachov Dmitiry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мы склонеям фамилии, имена и слова вообще с помощью таблицы правил и следующей функции, которая входит в разные алгоритмы - склонение имен, числительных и т.д. Учитывает все правила, что внесешь в таблицу правил. Минус, необходимо иметь правило в таблице, иначе слово останется в именительном падеже.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
FUNCTION padej(Word IN VARCHAR2, WType IN VARCHAR2, Sex IN VARCHAR2, Pad IN VARCHAR2) RETURN VARCHAR2 IS

  -- Курсор для выборки правил склонения
  CURSOR cs1 IS SELECT t.z, t.rp, t.dp, t.tip, t.pol, t.vp, t.tp, t.pp
    FROM ps.fio t
    WHERE t.pol=Sex
    AND t.tip=WType
    ORDER BY length(t.z) DESC;
  fio_ cs1%ROWTYPE;

  -- флаг, сигнализирующие, что окончание найдено
  found_flag BOOLEAN:=FALSE;
  -- для хранения длины окончания из таблицы FIO
  lzw INTEGER:= 0 ;
  -- для хранения длины слова
  lw INTEGER;
  -- для хранения результатов склонения
  newz_w VARCHAR2 ( 55 );
  -- для хранения окончания исходного слова
  cut VARCHAR2( 50 );

BEGIN
  -- Получим длину Ф., И., О., переданных через параметры
  lw :=length(Word);

  FOR fio_ IN cs1 LOOP
    lzw :=length(fio_.z);
    IF NOT(lw<lzw) THEN -- (#3) сравнение длины фамилии и окончания
      cut:=substr(Word, (lw-lzw)+ 1 );
      IF (cut=fio_.z) THEN  -- (#4) если окончание найдено
        found_flag:=TRUE; -- то установим флаг
        -- и отрежем от фамилии окончание
        newz_w:=substr(Word,  1 , (lw-lzw));
        -- Подставляем окончание, соответствующее склонению
        IF Upper(pad) = 'ROD' THEN -- (#5)
          newz_w:=newz_w||fio_.rp;
        ELSIF Upper(pad) = 'DAT' THEN
          newz_w:=newz_w||fio_.dp;
        ELSIF Upper(pad) = 'VIN' THEN
          newz_w:=newz_w||fio_.vp;
        ELSIF Upper(pad) = 'TVOR' THEN
          newz_w:=newz_w||fio_.tp;
        ELSIF Upper(pad) = 'PRED' THEN
          newz_w:=newz_w||fio_.pp;
        ELSE
          found_flag:=FALSE;
        END IF; -- (#5)

        EXIT; -- прекращаем поиск окончаний

      END IF; -- (#4)
    END IF; -- (#3) конец сравнения длины фамилии и окончания

  END LOOP;

  -- если окончание найдено, то возвращаем слово, иначе NULL
  IF found_flag=TRUE THEN
    RETURN(newz_w);
  ELSE
    RETURN(NULL);
  END IF;
END padej;
Пример таблицы в файле
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666800
Фотография dmidek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимор Конев dmidek Я
А кроме корейцев есть ещё много национальностей, где фамилии отличаются от стандартов русских. Хоть немецкие взять, к примеру.

Почеиу ?
Немецкие фамилии в немецком языке действительно не склоняются, но в русском склоняются нормально.
"Все рады мудрому решению канцлера Шредера" :-)
Хорошо, а просклоняй мне, к примеру, Вальтер Инга...
Полный вариант склонения композитора Евгения Доги.
Помните "Музыка Евгения Доги, слова ..."
Если это женщина по фамилии Вальтер, то тоже ничего специфического.
"Мы критикуем статью товарища Коллонтай"
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33666972
OracleX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коллеги, спасибо за исходники.

Георгий, сочувствую Вам, похоже автор исходника по молодости игнорировал стандарты и рекомендации
программирования на PL/SQL. Да и путанник был великий.

Коснусь только спецификации пакета.

1) Учитывая русскую специфику процедуры склонения фамилии в нужном падеже
имеет ли смысл вводить дополнительно функцию GetFIOPadeg?

На мой взгляд, достаточно padeg_FIO.

2) Падеж задается первой буквой своего названия: "и", "р", "д", "в", "т", "п"
и не зависит от регистра буквы.

Я бы разрешил только большие буквы "И"..."П", чтобы не наводить тень не плетень.

Строгость и краткость спецификаций пакета способствуют отодвиганию порога сложности
при крупномасштабном программировании.

3) Перенести из спецификации пакета в тело пакета все, что не предполагается использовать из других пакетов.
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33667022
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
функция Padeg_Word была переведена с 1С (мною), но всю логику я не трогал,
даже не вдавался в подробности.
GetFIOPadeg сделана для удобства - что бы падеж задавать по номерю.
Я автор только Get_F_I_O, GET_SEX (были давно написаны) и IIF, str_Right, str_Left (для удобства перевода с 1С) - если их можно как то переделать - готов выслушать предложения.
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33667249
OracleX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
geo_lifeGetFIOPadeg сделана для удобства - что бы падеж задавать по номерю. andrey_anonymous элегантно этим и воспользовался.

Однако, сомневаюсь, что подобный случай использования оправдывает
усложнение спецификации (применительно к склонению фамилий).

Кроме того, в наличии две фунции с разными именами, которые делают одно и то же.

Если уж очень надо, то используйте Overloading Subprogram Names
(PL/SQL User's Guide and Reference).
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33667314
Фотография geo_life
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OracleX geo_lifeGetFIOPadeg сделана для удобства - что бы падеж задавать по номерю. andrey_anonymous элегантно этим и воспользовался.

Однако, сомневаюсь, что подобный случай использования оправдывает
усложнение спецификации (применительно к склонению фамилий).

Кроме того, в наличии две фунции с разными именами, которые делают одно и то же.

Если уж очень надо, то используйте Overloading Subprogram Names
(PL/SQL User's Guide and Reference).
ДА, согласен. Надо будет переделать GetFIOPadeg с учетом Overloading Subprogram Names. Спасибо.
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33713657
valerytin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
create or replace function snp_case(
-- Падежная форма ФИО (Surname, Name and Patronymic in Case form)
-- valerytin, hexcept@narod.ru, 2003-11-18
 p_fio in varchar2,    -- строка,содержащая фамилию,имя и отчество
 p_padzh in varchar2,  -- падеж (бувквы русскиe): 'р'|'Р'-родительный,
                        -- 'д'|'Д'-дательный,etc., либо цифры:
                        -- 1-именительный, 2-родительный, 3-дательный, etc. 
 p_fio_fmt in varchar2 default 'ФИО',   -- формат входной строки-ФИО (т.е.
                                        -- 'Алексей Немов'->'ИФ',
                                        -- 'Ольга Львовна Гидова-Бережная'->
                                        -- 'ИОФ',etc.)
 p_sex in varchar2 default null         -- пол 'ж'|'Ж'|'м'|'М'
 ) return varchar2                      -- вывод в нужном падеже
 is
 l_pdzh_chr varchar2( 1 );
 l_pdzh pls_integer;
 l_sex varchar2( 1 ):=substr(ltrim(lower(p_sex)), 1 , 1 );
 l_tailchr varchar2( 1 );
 l_nmlen number( 2 , 0 );
 l_ul varchar2( 1 ):='N';
 l_uf varchar2( 1 ):='N';
 l_um varchar2( 1 ):='N';
 l_name_s varchar2( 80 );
 l_name_n varchar2( 80 ):=null;
 l_name_p varchar2( 80 ):=null;
 l_fio varchar2( 500 );
 l_fname varchar2( 80 );
 l_mname varchar2( 80 );
 l_fullname varchar2( 500 ):=ltrim(rtrim(p_fio,' -'),' -');
 l_pos pls_integer;
 l_fio_fmt varchar2( 3 ):=nvl(upper(substr(ltrim(p_fio_fmt), 1 , 3 )),'ФИО');
--
 function single_space(
  p_data varchar2
  ,p_dv varchar2 default ' '
  ) return varchar2
  is
  v_str varchar2( 2000 ):=p_data;
 begin
  while instr(v_str,p_dv||p_dv)> 0  loop
   v_str:=replace(v_str,p_dv||p_dv,p_dv);
  end loop;
  return v_str;
 end single_space;
--
 function term_cmp(
  s in varchar2,
  t in varchar2
 ) return boolean
 is
 begin
  if nvl(length(s), 0 )<nvl(length(t), 0 ) then return false; end if;
  if substr(lower(s),-length(t))=t then return true; else return false; end if;
 end term_cmp;
--
 procedure chng(
  s in out varchar2,
  n in number,
  pzrod in varchar2,
  pzdat in varchar2,
  pzvin in varchar2,
  pztvo in varchar2,
  pzpre in varchar2
 )
 is
 begin
  if l_pdzh= 1  then null;
  else
   select
    substr(s, 1 ,length(s)-n)||
     decode(l_pdzh, 2 ,pzrod, 3 ,pzdat, 4 ,pzvin, 5 ,pztvo, 6 ,pzpre)
   into s
   from dual;
  end if;
 end chng;
--
 procedure prep(
  fnm in out varchar2,
  lfm2 in out varchar2
 )
 is
 pp varchar2( 1 ):=substr(lfm2, 1 , 1 );
 nm varchar2( 80 );
 begin
  l_pos:=instr(fnm,' ');
  if l_pos> 0  then
   nm:=substr(fnm, 1 ,l_pos- 1 );
   fnm:=ltrim(substr(fnm,l_pos+ 1 ));
   l_pos:=instr(fnm,' ');
  else
   nm:=fnm; fnm:=null;
  end if;
  if pp='Ф' then
   l_name_s:=nm;
   lfm2:=replace(lfm2,'Ф');
  elsif pp='И' then
   l_fname:=nm;
   lfm2:=replace(lfm2,'И');
  elsif pp='О' then
   l_mname:=nm;
   lfm2:=replace(lfm2,'О');
  end if;
 end;
--
begin   -- snp_case()
 l_fullname:=replace(replace(single_space(l_fullname),' -','-'),'- ','-');
 if l_fullname is null then return p_fio; end if;
 if substr(l_fio_fmt, 1 , 1 ) not in ('Ф','И','О') then return p_fio; end if;
 if nvl(substr(l_fio_fmt, 2 , 1 ),'Ф') not in ('Ф','И','О')
 then return p_fio; end if;
 if nvl(substr(l_fio_fmt, 3 , 1 ),'Ф') not in ('Ф','И','О')
 then return p_fio; end if;
-- оглы, кызы:
 if lower(ltrim(rtrim(l_fullname))) like '%оглы%' and length(l_fullname)> 4 
 then
  l_name_p:=substr(l_fullname,instr(lower(l_fullname),'оглы'), 4 );
  l_fullname:=
   replace(replace(replace(replace(l_fullname,'оглы',null),'Оглы',null),
   'ОГЛЫ',null),'  ',' ');
  l_sex:=nvl(l_sex,'м');
 elsif lower(ltrim(rtrim(l_fullname))) like '%кызы%' and length(l_fullname)> 4 
 then
  l_name_p:=substr(l_fullname,instr(lower(l_fullname),'кызы'), 4 );
  l_fullname:=
   replace(replace(replace(replace(l_fullname,'кызы',null),'Кызы',null),
   'КЫЗЫ',null),'  ',' ');
  l_sex:=nvl(l_sex,'ж');
 end if;
 loop
  if l_fullname is not null then prep(l_fullname,l_fio_fmt); else exit; end if;
 end loop;
 l_nmlen:=nvl(length(l_name_s), 0 );
 l_pdzh_chr:=upper(substr(p_padzh, 1 , 1 ));
 select decode(l_pdzh_chr,'И', 1 ,'Р', 2 ,'Д', 3 ,'В', 4 ,'Т', 5 ,'П', 6 , 0 )
 into l_pdzh from dual;
 if l_pdzh= 0  then
  begin
   l_pdzh:=to_number(l_pdzh_chr);
   exception when others then return p_fio;
  end;
 end if;
 if nvl(l_sex,'z') not in ('м','ж') then    -- если пол не определен,
-- то пробуем определить его по отчеству:
  if l_mname is not null 
     and (upper(substr(l_mname,- 1 ))='Ч' or lower(l_name_p) like 'оглы')
  then l_sex:='м'; else l_sex:='ж';
  end if;
 end if;
 if l_name_s is not null then  -- фамилия
  if upper(l_name_s)=l_name_s then l_ul:='Y'; end if;
-- Предусмотрим обработку сдвоенной фамилии:
  if instr(l_name_s,'-')> 0  and lower(l_name_s) not like 'тер-%' then
   l_name_n:=
    substr(l_name_s, 1 ,instr(l_name_s,'-')- 1 )||' '||l_fname||' '||l_mname;
   l_fio:=snp_case(l_name_n,p_padzh,'ФИО',l_sex);
   l_name_n:=substr(l_fio, 1 ,instr(l_fio,' ')- 1 )||'-';
   l_name_s:=substr(l_name_s,instr(l_name_s,'-')+ 1 );
  end if;
  l_tailchr:=lower(substr(l_name_s,- 1 ));
  if l_sex='м' then  -- мужчины
   if l_tailchr not in ('о','е','у','ю','и','э','ы') then
    if l_tailchr='в' then
     chng(l_name_s, 0 ,'а','у','а','ым','е');
    elsif l_tailchr='н' and term_cmp(l_name_s,'ин') then
     chng(l_name_s, 0 ,'а','у','а','ым','е');
    elsif l_tailchr='ц' and term_cmp(l_name_s,'ец') then
     if l_nmlen> 3  and substr(l_name_s,- 3 ) in ('аец','еец','иец','оец','уец')
     then
      chng(l_name_s, 2 ,'йца','йцу','йца','йцем','йце');
     elsif l_nmlen> 3  
      and lower(substr(l_name_s,- 3 )) in (
       'тец','бец','вец','мец','нец','рец','сец') 
      and lower(substr(l_name_s,- 4 , 1 )) in (
       'а','е','и','о','у','ы','э','ю','я','ё')
     then
      chng(l_name_s, 2 ,'ца','цу','ца','цом','це');
     elsif l_nmlen> 3  and lower(substr(l_name_s,- 3 ))='лец' then
      chng(l_name_s, 2 ,'ьца','ьцу','ьца','ьцом','ьце');
     else
      chng(l_name_s, 0 ,'а','у','а','ом','е');
     end if;
    elsif l_tailchr='х' and (term_cmp(l_name_s,'их') or term_cmp(l_name_s,'ых'))
    then
     chng(l_name_s, 0 ,null,null,null,null,null);
    elsif l_tailchr in (
     'б','г','д','ж','з','л','м','н','п','р','с','т','ф','х','ц','ч','ш','щ')
    then
     chng(l_name_s, 0 ,'а','у','а','ом','е');
    elsif
     l_tailchr='я' and not(term_cmp(l_name_s,'ия') or term_cmp(l_name_s,'ая'))
    then
     chng(l_name_s, 1 ,'и','е','ю','ей','е');
    elsif l_tailchr='а' and not(term_cmp(l_name_s,'иа')
       or term_cmp(l_name_s,'уа')) then
     chng(l_name_s, 1 ,'и','е','у','ой','е');
    elsif l_tailchr='ь' then
     chng(l_name_s, 1 ,'я','ю','я','ем','е');
    elsif l_tailchr='к' then
     if l_nmlen> 4  and term_cmp(l_name_s,'ок') then
      chng(l_name_s, 2 ,'ка','ку','ка','ком','ке');
     elsif l_nmlen> 4  and (term_cmp(l_name_s,'лек')
        or term_cmp(l_name_s,'рек')) then
      chng(l_name_s, 2 ,'ька','ьку','ька','ьком','ьке');
     else
      chng(l_name_s, 0 ,'а','у','а','ом','е');
     end if;
    elsif l_tailchr='й' then
     if l_nmlen> 4  then
      if (term_cmp(l_name_s,'ский') or term_cmp(l_name_s,'цкий')) then
       chng(l_name_s, 2 ,'ого','ому','ого','им','ом');
      elsif term_cmp(l_name_s,'ой') then
       chng(l_name_s, 2 ,'ого','ому','ого','им','ом');
      elsif term_cmp(l_name_s,'ый') then
       chng(l_name_s, 2 ,'ого','ому','ого','ым','ом');
      elsif lower(substr(l_name_s,- 3 )) in ('рий','жий','лий','вий','дий',
       'бий','гий','зий','мий','ний','пий','сий','фий','хий')
      then
       chng(l_name_s, 1 ,'я','ю','я','ем','и');
      elsif term_cmp(l_name_s,'ий') then
       chng(l_name_s, 2 ,'его','ему','его','им','им');
      else
       chng(l_name_s, 1 ,'я','ю','я','ем','е');
      end if;
     else
      chng(l_name_s, 1 ,'я','ю','я','ем','е');
     end if;
    end if;
   end if;
  elsif l_sex='ж' then  -- женщины
   if lower(substr(l_name_s,- 3 )) in ('ова','ева','ына','ина','ена') then
    chng(l_name_s, 1 ,'ой','ой','у','ой','ой');
   elsif term_cmp(l_name_s,'ая') and lower(substr(l_name_s,- 3 , 1 )) in ('ц') then
    chng(l_name_s, 2 ,'ей','ей','ую','ей','ей');
   elsif term_cmp(l_name_s,'ая') then
    chng(l_name_s, 2 ,'ой','ой','ую','ой','ой');
   elsif term_cmp(l_name_s,'ля') or term_cmp(l_name_s,'ня') then
    chng(l_name_s, 1 ,'и','е','ю','ей','е');
   elsif term_cmp(l_name_s,'а') and lower(substr(l_name_s,- 2 , 1 )) in ('д') then
    chng(l_name_s, 1 ,'ы','е','у','ой','е');
   end if;
  end if;
 end if;
 if l_fname is not null then  -- имя
  if upper(l_fname)=l_fname then l_uf:='Y'; end if;
  l_tailchr:=lower(substr(l_fname,- 1 ));
  if l_sex='м' then  -- мужчины
   if l_tailchr not in ('е','и','у') then
    if upper(l_fname)='ЛЕВ' then
     chng(l_fname, 2 ,'ьва','ьву','ьва','ьвом','ьве');
    elsif l_tailchr in (
     'б','в','г','д','з','ж','к','м','н','п','р','с','т','ф','х','ц',
     'ч','ш','щ')
    then
     chng(l_fname, 0 ,'а','у','а','ом','е');
    elsif l_tailchr='а' then
     chng(l_fname, 1 ,'ы','е','у','ой','е');
    elsif l_tailchr='о' then
     chng(l_fname, 1 ,'а','у','а','ом','е');
    elsif l_tailchr='я' then
     if term_cmp(l_fname,'ья') then
      chng(l_fname, 1 ,'и','е','ю','ей','е');
     elsif term_cmp(l_fname,'ия') then
      chng(l_fname, 1 ,'и','е','ю','ей','е');
     else
      chng(l_fname, 1 ,'и','е','ю','ей','е');
     end if;
    elsif l_tailchr='й' then
     if term_cmp(l_fname,'ай') then
      chng(l_fname, 1 ,'я','ю','я','ем','е');
     else
      if term_cmp(l_fname,'ей') then
       chng(l_fname, 1 ,'я','ю','я','ем','е');
      else
       chng(l_fname, 1 ,'я','ю','я','ем','и');
      end if;
     end if;
    elsif l_tailchr='ь' then
     chng(l_fname, 1 ,'я','ю','я','ем','е');
    elsif l_tailchr='л' then
     if term_cmp(l_fname,'авел') then
      chng(l_fname, 2 ,'ла','лу','ла','лом','ле');
     else
      chng(l_fname, 0 ,'а','у','а','ом','е');
     end if;
    end if;
   end if;
  elsif l_sex='ж' then  -- женщины
   if l_tailchr='а' and nvl(length(l_fname), 0 )> 1  then
    if lower(substr(l_fname,- 2 )) in ('га','ха','ка','ша','ча','ща','жа') then
     chng(l_fname, 1 ,'и','е','у','ой','е');
    else
     chng(l_fname, 1 ,'ы','е','у','ой','е');
    end if;
   elsif l_tailchr='я' and nvl(length(l_fname), 0 )> 1  then
    if term_cmp(l_fname,'ия') and lower(substr(l_fname,- 4 )) in ('ьфия') then
     chng(l_fname, 1 ,'и','е','ю','ей','е');
    elsif term_cmp(l_fname,'ия') then
     chng(l_fname, 1 ,'и','и','ю','ей','и');
    else
     chng(l_fname, 1 ,'и','е','ю','ей','е');
    end if;
   elsif l_tailchr='ь' then
    if term_cmp(l_fname,'вь') then
     chng(l_fname, 1 ,'и','и','ь','ью','и');
    else
     chng(l_fname, 1 ,'и','и','ь','ью','ье');
    end if;
   end if;
  end if;
 end if;
 if l_mname is not null then  -- отчество
  if upper(l_mname)=l_mname then l_um:='Y'; end if;
  l_tailchr:=lower(substr(l_mname,- 1 ));
  if l_sex='м' then  -- мужчины
   if l_tailchr='ч' then
    chng(l_mname, 0 ,'а','у','а','ем','е');
   end if;
  elsif l_sex='ж' then  -- женщины
   if l_tailchr='а' and length(l_mname)<> 1  then
    chng(l_mname, 1 ,'ы','е','у','ой','е');
   end if;
  end if;
 end if;
-- окончательная конкатенация
 l_fio_fmt:=nvl(upper(substr(ltrim(p_fio_fmt), 1 , 3 )),'ФИО'); -- м.б. рекурсия...
 l_pos:= 1 ;
 loop
  if l_pos> 1  then l_fullname:=l_fullname||' '; end if;
  select
   l_fullname||decode(substr(l_fio_fmt,l_pos, 1 ),'Ф',
    decode(l_ul,'Y',upper(l_name_n||l_name_s),l_name_n||l_name_s),'И',
    decode(l_uf,'Y',upper(l_fname),l_fname),'О',
    decode(l_um,'Y',upper(replace(replace(l_mname,'оглы',null),'кызы',null)||
    decode(instr(l_mname,'-'), 0 ,' ',null)||l_name_p),replace(replace(l_mname,
    'оглы',null),'кызы',null)||decode(instr(l_mname,'-'), 0 ,' ',null)||l_name_p))
  into l_fullname from dual;
  l_pos:=l_pos+ 1 ;
  if l_pos>nvl(length(l_fio_fmt), 0 ) then exit; end if;
 end loop;
 return nvl(ltrim(rtrim(l_fullname,' -'),' -'),
  ltrim(rtrim(single_space(p_fio),' -'),' -'));
end snp_case;
...
Рейтинг: 0 / 0
Склонение фамилий. (Вариант решения)
    #33713709
Grami
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://]http://www.delphikingdom.com/asp/viewitem.asp?catalogid=412


Читаем и проникаемся. А потом прикручиваем к ораклухе и юзаем :)
Хотя на *никсах это не вариант.
...
Рейтинг: 0 / 0
25 сообщений из 40, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Склонение фамилий. (Вариант решения)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]