logo

[ELMA3] Особенности разработки для Oracle

Программы и настройки

  1. Oracle SQL Developer.
  2. Для ELMA в папке bin сервера должны лежать библиотеки из Libs\Oracle.
  3. Правильно настроенная конфигурация. Для сохранения и загрузки настроек используется класс OracleSettingsSection, соответсвено, в конфиге нужно его указать вместо базового.
<section name="main" type="EleWise.ELMA.Extensions.Oracle.OracleSettingsSection, EleWise.ELMA.Extensions.Oracle" />
4. Нужна правильная строка подключения к БД.
5. В настройке провайдера добавилось 2 новых свойства: sysUser и sysPassword. Это логин и пароль глобального администратора на Oracle сервере.
<main connectionStringName="MainDB" type="EleWise.ELMA.Extensions.Oracle.OracleProvider, EleWise.ELMA.Extensions.Oracle" backupEnabled="false" sysUser="login" sysPassword="password"/>
В Oracle своеобразная структура баз. По сравнению с MS SQL и Firebird, где есть понятие БД (с алиасом), его файл и отдельно пользователи к ней, в Oracle БД = пользователь. То есть когда мы в строке соединения прописываем под каким пользователем подключаться, мы автоматом определяем к какой базе на сервере конектиться. Имя пользователя должно начинаться с префикса c##. Параметры sysUser и sysPassword не обязательны, но если они не заданы и БД еще не создана, то придется сделать это вручную. Скрипт создания базы и раздачи нужных прав на схему:
create user c##login identified by password;
grant all PRIVILEGES to c##login ;
GRANT SELECT ON  "SYS"."GV_$RESERVED_WORDS" TO c##login;
GRANT SELECT ON  "SYS"."V_$RESERVED_WORDS" TO c##login;
Для удаления базы используется команда:
drop user elma3 cascade;

SQL-запросы

При разработке нужно всегда помнить, что в Oracle около 1200 ключевых слов. Каждое ключевое слово в запросах должно быть взято в кавычки. При этом нужно помнить, что такие названия в кавычках становятся регистрозависимыми. К примеру, UID и "Uid" это две разные колонки для Oracle. Список ключевых слов хранится прямо в базе, можно получить их запросом:
select keyword from sys.v_$reserved_words

Хранимые процедуры

Так просто в Oracle табличку из функции не вернуть. Лучше всего это делать через кастомные типы. Для того, чтобы вернуть табличку, нужно создать тип для строки и тип для таблички:
CREATE TYPE NOMENCLATURETREE_row as object
        ( "Id" integer
        , "Name" nvarchar2(2000)
        , PARENTGROUP integer
        , LinkId integer
        , nodetypeuid raw(16));

CREATE TYPE NOMENCLATURETREE_tbl as table of NOMENCLATURETREE_row;
После этого можно писать процедуру, которая возвращает результат типа таблица:
create or replace function NOMENCLATURETREE
(p_YEARNOMEN integer)
RETURN NOMENCLATURETREE_tbl PIPELINED
is
	temp NOMENCLATURETREE_row;
begin
	temp := NOMENCLATURETREE_row(null,null,null,null,null);
	FOR i IN (
		select
			dg."Id" as "Id",
			case
				when (rpi."Id" is not null) then rp."Name"
				when (dl."Id" is not null) then dr2."Name"
				else dg."Name"
			end as "Name", 
			dg.parentgroup, 
			case 
			  when (dl."Id" is not null) then dl.DEPOSITORY
			else dg."Id" end as LinkId, 
			dg.typeuid as nodetypeuid  
		from depositorygroup dg
			left join depositorygroup dr on dr."Id" = dg."Id"
			left join registrationplaceitem rpi on rpi."Id" = dr."Id"
			left join REGISTRATIONPLACE rp on rp."Id" = rpi.registrationplace
			left join depositorylink dl on dl."Id" = dr."Id"
			left join depositorygroup dr2 on dl.depository = dr2."Id"
		start with 1=1
			and dg.parentgroup is null
			and exists
			(select 1 from registrationplaceitem regpli, accountingyear ay
			where 1=1
			and dg."Id" = regpli."Id"
			and ay."Id" = regpli.ACCOUNTINGYEAR
			and ay."Year" = p_YEARNOMEN)
		connect by nocycle prior dg."Id" = dg.parentgroup
	)
	LOOP
		temp."Id" := i."Id";
		temp."Name" := i."Name";
		temp.PARENTGROUP := i.PARENTGROUP;
		temp.LinkId := i.LinkId;
		temp.nodetypeuid := i.nodetypeuid;
		PIPE ROW (temp);
	END LOOP;
	RETURN;
end NOMENCLATURETREE;

Рекурсивные процедуры

Oracle поддерживает стандарт по рекурсивным запросам только с 11-ой версии. У нас должно еще работать и на 10-ой. До 11 версии в Oracle существовал только свой синтаксис (через CONNECT BY). Подробнее написано здесь (глава про Oracle).