На параметрите на абонати и изхода в Oracle

Най-доброто от практическия опит на използване на правата на инициатора на обаждането и функции.

Въпрос: Напоследък съм много пъти, използвани AUTHID CURRENT_USER оператор (вдясно първоизточника права заявяващ на разговора). Често пиша инструменти за други разработчици на моя екип и да се определят на централно SHARED_CODE схема. Когато се определи програма с правата на обаждащия се, всички разработчици могат да се обадят на тази програма и тя автоматично ще изпълнява желаните операции върху тези обекти, които са в собствена схема на разработчика. Но понякога ми се сблъскате с проблеми, свързани с правата на инициатора. В следващия проект, трябва да се работи с файлове на операционната система чрез UTL_FILE. По-специално, пишем текста от файловете, и текстът трябва да е форматиран в най-различни форми. Затова реших да напиша "пише във файл", която ще изпълнява всички операции с UTL_FILE, и ще позволи на потребителите да определят форматирането със собствените си функции. По този начин, те ще имат максимална гъвкавост за форматиране. Но това не изглежда да работят. Написах една програма "пише във файл" с права заявяващ, но тя отказва да се обадите на програмата инициатор форматиране. Каква е грешката?

Отговор: Не няма грешка. Ти просто се срещна към ограничаване на правата на инициатора на повикване. За щастие, не мога да ви помогне да се справите с това ограничение и да се постигне желания.

Обикновено всичко, което е необходимо е да се напише на основната програма, която връща контрола на рутината, чието име все още не е известно кога за написването на програмата. По този начин, програмата трябва по време на разговор, за да се разбере коя програма е причинило.

Един от начините, които можете да използвате механизма за връщане е използването на динамичен полиморфизъм и Oracle типове обекти. Това е най-удобният начин, който трябва да бъде разгледан по друго време. И този път аз ще ви покажа как можете да използвате възвръщаемостта и правата на инициатора на обаждането, за да получите желания резултат.

Нека започнем с някои от принципите на правата на заявяващ, които важат за всички SQL-предложения (статични и динамични), извършени в PL / SQL блок. В случва правата кандидатстване заявяващ, имената на региона и съответните изчисления привилегия по време на обаждането (по-късно ролите се признават и да се използват за изчисляване на тези привилегии). право на обаждащия се прилага по отношение на следните предложения:
  • Предложения за манипулиране на данни SELECT, INSERT, обновяване и изтриване
  • Предложение за управление на сделка LOCK TABLE
  • Предложения за контрол на курсора и Изключване-For
  • Всички динамични SQL-предложения (изпълнение IMMEDIATE, отворен за и DBMS_SQL)

Да предположим, че да включва клауза за AUTHID CURRENT_USER в заглавната част на моята програма. Когато се съберат тази програма, настоящата схема все още се нуждаят директно получава привилегии за всички обекти, споменати в програмата.

Един от най-очевидните изводи, които могат да се направят от това е, че изявлението AUTHID CURRENT_USER няма да се прилага за статични повиквания други съчетания, наречени от програми с права заявяващ.

Статично програма обаждане, когато програмата се определя по време на компилация. Например, следния кодов фрагмент, PROC1 статично причинява PROC2.

По време на компилация PROC1 в схемата ABC, Oracle Database позволява връзка към PROC2 връзка с привилегиите на тази схема. Сега предполагам, че базата данни търси PROC2 процедура по схема ABC. Уважи ЕXECUTE на ABC.proc1 друга схема, като DEF, която има своя собствена процедура PROC2. Когато един потребител се свързва с DEF изпълнява ABC.proc1, че потребителят винаги ще тече ABC.proc2, не DEF.proc2.

Означава ли това, че е невъзможно да се създаде работна програма "пише във файл" с права заявяващ? Не съвсем. Всъщност можете да получите на Oracle за динамично изберете коя програма тя трябва да се обадя, но е необходимо да се прилага възможността за динамично PL / SQL.

Помислете две прости демонстрации на въздействието на правата заявяващ, и тогава аз ще покажа динамичен PL / SQL- "заобикаляйки"

Първо, помислете AUTHID текущия потребител по отношение на обектите на данни. Обява 1 в схема HR създадени права извикване на процедура инициатор show_my_data, който показва броя на редовете в таблицата с маса my_data (10). Ние издаваме привилегията ИЗПЪЛНЯВАТ SCOTT потребител да се позове на програмата. също имат маса my_data, където една линия в схемата SCOTT. Тогава SCOTT причинява HR.show_my_data и програмата показва една, вместо 10 линии.

Обява 1: Създаване и призова show_my_data

Както можете да видите, независимо от факта, че аз се завтече show_my_data процес HR, програмата ми показва броя на my_data SCOTT маса потребител.

Но сега нека се опитаме да се създаде "запис във файл". На първо място, "по подразбиране" ще създаде директория на базата данни на функцията на потребителско HR и формат (текст преобразува в главни букви):

На следващо място, създаване на много проста програма, показана на Обява 2, който изпълнява "пише във файл", и даде на потребителя SCOTT да го наричат.

Обява 2: Създаване write_to_file

След това се присъедини като SCOTT, създаване на форматиране функция, която преобразува текста в малки букви, като се обадите write_to_file както е показано на Обява 3.

Обява 3: Създаване format_line (и предизвикателство write_to_file)

За съжаление, аз имам следния текст myfile.txt в изходния файл:

Така че, не е много вероятно, че бихме могли да използваме призива на инициатора дясната програма? Е, може би се опита друг начин: с помощта на динамичен SQL.

Пренаписах оригиналната програма write_to_file в човешки ресурси, както е показано на Обява 4.

Обява 4: Създаване на модифициран write_to_file

Имайте предвид, че се преместих на предизвикателството format_line функции предлагат ИЗПЪЛНЯВАТ ПЪРВИЧНА. Затова се обадих на функцията динамичен PL / SQL блок. И сега се присъедини като SCOTT и се обадете write_to_file:

И тук виждаме следното съдържание в myfile.txt на изходния файл:

О, тя работи! Възможно ли е това?

Преместването на призива програма в динамично изпълнена PL / SQL блок, разговорът стана извършва от предложението, което може да се приложи правилната повикващия: ИЗПЪЛНЯВАТ ПЪРВИЧНА. По този начин, устройството е сега изпълнява под SCOTT ", тъй като той се нарича версия format_line SCOTT потребител.

Поради това, че е правилно, тъй като създателя на разговора може да се използва за извършване на стека на повикване с помощта на динамичен PL / SQL.

Имайте предвид, моля те, че динамичните показатели на PL / SQL-съчетания-бавно, отколкото статична. За дълго бягане програми, тези разходи ще бъдат незначителни, но имайте това предвид, когато създавате програми, които се изпълняват много бързо.

Аз в сравнение изпълнението на статичен и динамичен старт на програмата, в която се призовава ПОТРЕБИТЕЛЯ и магазините тази стойност в локална променлива. На Run 100000 пъти с помощта на статично покана се осъществява в продължение на 2,83 секунди. Dynamic стартирането се извършва в 6.66 секунди.

Един последен бележка: Алтернативен начин за постигане на същия ефект (избор на програма да се изпълнява по време на работа), е използването на динамичен полиморфизъм. Тази техника е изградена в типове обекти в PL / SQL-а именно, чрез създаване на йерархия от типове обекти с ключова дума за. За повече информация относно типове обекти и динамичен полиморфизъм в PL / SQL, проучване Глава 12, "Използване на PL / SQL С типове обекти" в Ръководство за Oracle Database PL / SQL потребителя и справочник.

Q: Аз вярвам, че функцията трябва да върне данните само чрез изявление за връщане. Защо PL / SQL ви позволява да използвате извън параметрите на функции? Може би в използването на тази функция има някаква специфика?

A: Аз са се образували някои насоки за структурата на функцията:
  • Не използвайте изход или вход посочените основания в списъка на параметрите на функция.
  • Връща всички данни в отчета за RETURN.
  • Възхвала само едно изявление RETURN в функция, осъществявана част да върне и да направи на последния ред в този раздел.
  • Ако е необходимо да се върне могат да бъдат използвани като съставни типове данни (запис събиране обект, и други подобни) няколко стойности, и промяна на функцията на процедурата, а след това използват OUT или IN OUT аргумент.

Защо Oracle ни позволява да използваме извън аргументи в функциите на списък параметър? Може би защото тя признава, че светът не е толкова черно и бяло, и създава много нюанси на сивото. Програмистите имат по-голяма свобода на избор, с много различни стилове на писане на код.

Аз съм много доволен, че Oracle не се отказва от практиката на използване на OUT-функционални параметри (което не е, между другото, всеобщо приет и общата практика в света на програмирането) в изпълнение на PL / SQL.

Моят опит с света на програмирането на С, например, показва, че предприемачите обикновено пишат функция, която връща код на връщане което показва дали функцията е завършила успешно. След това те се използват извън аргументи в списъка с параметри за връщане на информация от функцията.

Не ми харесва този подход, особено в PL / SQL, но аз чувствам, че имам нужда от по-голяма гъвкавост език, не по-малко. И трябва да се разработи свой собствен потребителски технологии, за да изберете кои PL / SQL възможности за използване и кои не са.

Разбира се, може да има ситуации, в които функцията с OUT-параметър полезни. Да разгледаме следния блок. source_code.more_data връща булеви, който се използва за излизане от цикъла, и го връща същата като OUT-аргумент структура на данни, който след това се обработва в цикъл.

Да, разбира се, не мога да пренапише кода, така че да използва функцията без OUT-параметър или процедура, но тя ще направи кода по-трудни и неудобни за четене.

Ето защо, ние очевидно не искам да правя Oracle функции с изход или вход параметър OUT е невалиден, но мисля, че този списък от възможности, става полезен само в определени случаи.