Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / геттер-пакеты для таблиц / 17 сообщений из 17, страница 1 из 1
29.01.2016, 22:17
    #39158998
proxy1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
часто в коде нашей системы (бизнес-логика написана на PL/SQL) бывает следующая ситуация:
в процедуру передается ключевое поле, но нужно далее по коду из этой же таблицы и другие поля подтягивать
в тоннах уже существующего в системе легаси-кода каждый раз пишутся запросы на вытягивание нужных полей
такой подход не очень нравится (код обрастает этими запросами), написал в итоге генератор спец пакетов, в которых для нужных таблиц содержатся функции-геттеры полей таблицы
получаются примерно такие пакеты:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
package p$table_name as

...

function some_column(pKey in some_type) return some_type;

...

end p$table_name;


кто-то задавался подобным вопросом и, если да, как решал?
...
Рейтинг: 0 / 0
29.01.2016, 22:54
    #39159008
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
proxy1,

Может, это будет полезно:
Pipelined Table Functions as Transformation Functions

Example 12-30 Pipelined Table Function Transforms Each Row to Two Rows
Код: plaintext
1.
2.
3.
4.
SELECT * FROM TABLE (
  refcur_pkg.f_trans (
    CURSOR (SELECT * FROM employees WHERE department_id = 60)
  )
);
...
Рейтинг: 0 / 0
29.01.2016, 23:05
    #39159014
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
а с другой стороны, подходов много. в частности:

1. передавать в подпрограмму параметр типа SOME_TABLE%ROWTYPE , вытащенный предварительно.
2. передавать ROWID записи, полученный ранее запросом FOR UPDATE , а там уже "подтягивать" нужные колонки запросом SELECT WHERE ROWID=:ROWID , либо делать DML для этого ROWID.
...
Рейтинг: 0 / 0
29.01.2016, 23:23
    #39159020
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
а еще есть ООП с объектными таблицами , но не думаю, что вы этим займетесь.
...
Рейтинг: 0 / 0
29.01.2016, 23:29
    #39159023
proxy1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
--Eugene--а еще есть ООП с объектными таблицами , но не думаю, что вы этим займетесь.
система уже крутится на обычных таблицах
а про ООП и PL/SQL...
ощущения, что оно, вроде как, есть, только никому не надо
...
Рейтинг: 0 / 0
29.01.2016, 23:35
    #39159025
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
proxy1,

так или иначе, переключать контекст каждый раз ради получения какого-то конкретного поля таблицы (а именно это вы делаете своими "getter-ами") - это очень и очень не comme il faut
...
Рейтинг: 0 / 0
29.01.2016, 23:39
    #39159028
proxy1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
--Eugene--proxy1,

так или иначе, переключать контекст каждый раз ради получения какого-то конкретного поля таблицы (а именно это вы делаете своими "getter-ами") - это очень и очень не comme il faut
ну, для комильфо осталось еще добавить генерацию геттера всей строки
...
Рейтинг: 0 / 0
30.01.2016, 08:38
    #39159097
qsdan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
Как то было дело реализовывал генератор. Для этого все поля таблицы классифицировались по нескольким признакам
1. тип данных
2. изменяемость (признак использовался при для генерации Setter-ов, или при его отсутствии Getter-ов c deterministic)
3. обязательность (для генерации процедуры вставки записей типа InsertRec(idpCountry integer) и формирования PK)
4. Английское наименование (использовалось для генерации имени функций с учетом регистра GetSystemName())
5. Русское наименование (для регенерации комментариев)
...
Рейтинг: 0 / 0
31.01.2016, 10:20
    #39159389
Ramin Hashimzade
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
proxy1часто в коде нашей системы (бизнес-логика написана на PL/SQL) бывает следующая ситуация:
в процедуру передается ключевое поле, но нужно далее по коду из этой же таблицы и другие поля подтягивать
в тоннах уже существующего в системе легаси-кода каждый раз пишутся запросы на вытягивание нужных полей
такой подход не очень нравится (код обрастает этими запросами), написал в итоге генератор спец пакетов, в которых для нужных таблиц содержатся функции-геттеры полей таблицы
получаются примерно такие пакеты:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
package p$table_name as

...

function some_column(pKey in some_type) return some_type;

...

end p$table_name;


кто-то задавался подобным вопросом и, если да, как решал?

функция которое будет возвращать rowtype?
...
Рейтинг: 0 / 0
31.01.2016, 18:27
    #39159535
orawish
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
proxy1--Eugene--а еще есть ООП с объектными таблицами , но не думаю, что вы этим займетесь.
система уже крутится на обычных таблицах
а про ООП и PL/SQL...
ощущения, что оно, вроде как, есть, только никому не надо
это (имхо) можно к теме вашего топика применить
мартышкин труд, если внимательно оценивать - вредный
...
Рейтинг: 0 / 0
19.11.2016, 21:11
    #39350348
proxy1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
orawishproxy1пропущено...

система уже крутится на обычных таблицах
а про ООП и PL/SQL...
ощущения, что оно, вроде как, есть, только никому не надо
это (имхо) можно к теме вашего топика применить
мартышкин труд, если внимательно оценивать - вредный
Опишу ситуацию с пояснениями и примерами.
Есть куча легаси-кода на PL-SQL (километры).
Практически вся бизнес-логика на PL-SQL и реализована.
В километрах этого кода есть обращения к таблицам для подтягивания значений нужных полей.
Пример:
Таблица
Код: plsql
1.
TUSER (ID number, USERNAME varchar2, DESCRIPTION varchar2)


Таблица
Код: plsql
1.
TOPERATIONTYPE (ID number, NAME varchar2)


Таблица
Код: plsql
1.
TOPERATION (ID number, OPERATION_DATE date, USER_ID number, OPERATION_TYPE_ID number)


Есть процедура PL/SQL:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
procedure DO_OPERATION(OPERATION_DATE date, OPERATION_TYPE_ID number, USER_ID number) is
vOperationTypeName varchar2(500);
begin
    ...
    /*допустим, тут по бизнес-логике надо вытянуть название типа операции
    раньше это выглядело как:

    вариант 1:
    select name  into vOperationTypeName from toperationtype where id = OPERATION_TYPE_ID;

    вариант 2:
    курсор в блоке объявлений (приведу его тут):
    cursor cOperationTypeInfo(cpOperationTypeId number) is
        select name  toperationtype where id = cpOperationTypeId;
    естественно, с последующим вызовом:
    open cOperationTypeInfo(OPERATION_TYPE_ID);
    fetch cOperationTypeInfo into vOperationTypeName;
    close cOperationTypeInfo ;

    сейчас это выглядит так:
    vOperationTypeName := p$OperationType.name(OPERATION_TYPE_ID);
   */
    ...
end DO_OPERATION;



в чем же тут:
orawishмартышкин труд, если внимательно оценивать - вредный?
...
Рейтинг: 0 / 0
19.11.2016, 22:12
    #39350362
геттер-пакеты для таблиц
proxy1 функции-геттеры полей таблицы
а что дает замена "select таблицаA..." на "call функцияA..."?
...
Рейтинг: 0 / 0
19.11.2016, 23:22
    #39350376
proxy1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
Нестандарт неsqlproxy1 функции-геттеры полей таблицы
а что дает замена "select таблицаA..." на "call функцияA..."?
А вот напишите их рядом и сравните (с учётом разрешения имён).
Как минимум, короче.
И, на мой взгляд, без обоснованных причин напрямую (без обёртки курсорами или функциями) запросы писать в PL/SQL - не очень комильфо.
...
Рейтинг: 0 / 0
20.11.2016, 06:32
    #39350411
кит северных морей
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
автор
Код: plsql
1.
    vOperationTypeName := p$OperationType.name(OPERATION_TYPE_ID);



вы на каждое поле каждой таблицы свой геттер пишете?
...
Рейтинг: 0 / 0
20.11.2016, 08:03
    #39350419
прагма тик
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
proxy1Как минимум, короче.
Код: sql
1.
2.
select * into переменная from таблица where ключ = значение
переменная := пакет_таблица.get(значение)



Во-первых, получать где-то поля одной таблица по ключу в отрыве от других джоинов и условий достаточно редкая для серверного plsql задача. Ну допустим, где-то приспичило на стороне сервера склеивать строку "...№ ... дата..." в отрыве от других данных - сэкономил 15 нажатий клавиш в трех местах, но вынужден давить клавиши, чтобы написать генератор и генерить на каждый ненужный случай функции, а потом тащить составное имя переменной ради использования одного-двух полей.
Во-вторых, получил расходы по памяти, цпу и возможно lio.
...
Рейтинг: 0 / 0
20.11.2016, 09:52
    #39350432
proxy1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
кит северных морейавтор
Код: plsql
1.
    vOperationTypeName := p$OperationType.name(OPERATION_TYPE_ID);



вы на каждое поле каждой таблицы свой геттер пишете?
Вот код функции, генерирующей пакеты:
Код: plsql
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.
CREATE OR REPLACE function PackageCodeForTable(
    pOwner in varchar2
    , pTableName in varchar2
    , pKeyFieldName in varchar2
) return clob is

GENERATION_INFO_TEMPLATE constant clob :=
'
/*******************************************************************************
    Сервисный пакет для таблицы ' || upper(pOwner) || '.' || upper(pTableName) || '
    Код пакета сгенерирован функцией PackageCodeForTable
    Дата: ' || to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') || '  
*******************************************************************************/
';

ROW_FUNCTION_SPEC_TEMPLATE constant clob := 
'
function AllColumns(pKey in {$OWNER}.{$TABLE_NAME}.{$KEY_FIELD_NAME}%type)
    return {$OWNER}.{$TABLE_NAME}%rowtype;
';

FUNCTION_SPEC_TEMPLATE constant clob := 
'
function {$FIELD_NAME}(pKey in {$OWNER}.{$TABLE_NAME}.{$KEY_FIELD_NAME}%type)
    return {$OWNER}.{$TABLE_NAME}.{$FIELD_NAME}%type;
';

ROW_FUNCTION_IMPL_TEMPLATE constant clob := 
'
function AllColumns(pKey in {$OWNER}.{$TABLE_NAME}.{$KEY_FIELD_NAME}%type)
    return {$OWNER}.{$TABLE_NAME}%rowtype is
vResult {$OWNER}.{$TABLE_NAME}%rowtype;
begin
    select  t.*
    into    vResult
    from    {$OWNER}.{$TABLE_NAME} t
    where   t.{$KEY_FIELD_NAME} = AllColumns.pKey
    ;
    
    return vResult; 
end AllColumns;
';

FUNCTION_IMPL_TEMPLATE constant clob := 
'
function {$FIELD_NAME}(pKey in {$OWNER}.{$TABLE_NAME}.{$KEY_FIELD_NAME}%type)
    return {$OWNER}.{$TABLE_NAME}.{$FIELD_NAME}%type is
vResult {$OWNER}.{$TABLE_NAME}.{$FIELD_NAME}%type;
begin
    select  t.{$FIELD_NAME}
    into    vResult
    from    {$OWNER}.{$TABLE_NAME} t
    where   t.{$KEY_FIELD_NAME} = {$FIELD_NAME}.pKey
    ;
    
    return vResult; 
end {$FIELD_NAME};
';

vResult clob;
vFunctionSpecificationCode clob;
vFunctionImplementationCode clob;
vPackageSpecificationCode clob;
vPackageImplementationCode clob;
vQueryTableColumns clob;
vTableColumn TStringArray; -- DDL создания типа: CREATE OR REPLACE TYPE TStringArray is varray(200) of varchar2(500);

begin
    vQueryTableColumns := 'select column_name from dba_tab_columns where owner = :pOwner and table_name = :pTableName order by column_id';
    execute immediate vQueryTableColumns bulk collect into vTableColumn using upper(pOwner), upper(pTableName);
    
    vPackageSpecificationCode := 'create package ' || pOwner || '.p#' || pTableName || ' as' || utl_tcp.crlf || GENERATION_INFO_TEMPLATE;

    vFunctionSpecificationCode := ROW_FUNCTION_SPEC_TEMPLATE;
    vFunctionSpecificationCode := replace(vFunctionSpecificationCode, '{$OWNER}', pOwner);
    vFunctionSpecificationCode := replace(vFunctionSpecificationCode, '{$TABLE_NAME}', pTableName);
    vFunctionSpecificationCode := replace(vFunctionSpecificationCode, '{$KEY_FIELD_NAME}', pKeyFieldName);
    vPackageSpecificationCode := vPackageSpecificationCode || vFunctionSpecificationCode;

    for i in 1..vTableColumn.count loop
        vFunctionSpecificationCode := FUNCTION_SPEC_TEMPLATE;
        vFunctionSpecificationCode := replace(vFunctionSpecificationCode, '{$OWNER}', pOwner);
        vFunctionSpecificationCode := replace(vFunctionSpecificationCode, '{$TABLE_NAME}', pTableName);
        vFunctionSpecificationCode := replace(vFunctionSpecificationCode, '{$KEY_FIELD_NAME}', pKeyFieldName);
        vFunctionSpecificationCode := replace(vFunctionSpecificationCode, '{$FIELD_NAME}', lower(vTableColumn(i)));
        
        vPackageSpecificationCode := vPackageSpecificationCode || vFunctionSpecificationCode;
    end loop;
    
    vPackageSpecificationCode := vPackageSpecificationCode || utl_tcp.crlf || 'end p#' || pTableName || ';' || utl_tcp.crlf;


    vPackageImplementationCode := 'create package body ' || pOwner || '.p#' || pTableName || ' as' || utl_tcp.crlf || GENERATION_INFO_TEMPLATE;    

    vFunctionImplementationCode := ROW_FUNCTION_IMPL_TEMPLATE;
    vFunctionImplementationCode := replace(vFunctionImplementationCode, '{$OWNER}', pOwner);
    vFunctionImplementationCode := replace(vFunctionImplementationCode, '{$TABLE_NAME}', pTableName);
    vFunctionImplementationCode := replace(vFunctionImplementationCode, '{$KEY_FIELD_NAME}', pKeyFieldName);
    vPackageImplementationCode := vPackageImplementationCode || vFunctionImplementationCode;

    for i in 1..vTableColumn.count loop
        vFunctionImplementationCode := FUNCTION_IMPL_TEMPLATE;
        vFunctionImplementationCode := replace(vFunctionImplementationCode, '{$OWNER}', pOwner);
        vFunctionImplementationCode := replace(vFunctionImplementationCode, '{$TABLE_NAME}', pTableName);
        vFunctionImplementationCode := replace(vFunctionImplementationCode, '{$KEY_FIELD_NAME}', pKeyFieldName);
        vFunctionImplementationCode := replace(vFunctionImplementationCode, '{$FIELD_NAME}', lower(vTableColumn(i)));
        
        vPackageImplementationCode := vPackageImplementationCode || vFunctionImplementationCode;
    end loop;
    
    vPackageImplementationCode := vPackageImplementationCode || utl_tcp.crlf || 'end p#' || pTableName || ';' || utl_tcp.crlf;
    
    
    vResult := vPackageSpecificationCode || '/' || utl_tcp.crlf || utl_tcp.crlf || utl_tcp.crlf || vPackageImplementationCode || '/'; 
    
    return vResult;
end PackageCodeForTable;
/

...
Рейтинг: 0 / 0
21.11.2016, 11:25
    #39350851
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
геттер-пакеты для таблиц
proxy1Как минимум, короче.
Вот это агрумент!
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / геттер-пакеты для таблиц / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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