<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3592984248764138907</atom:id><lastBuildDate>Mon, 28 May 2012 07:35:35 +0000</lastBuildDate><category>dbms_stat_funcs</category><category>subquery</category><category>apex</category><category>DBMS_EPG</category><category>package</category><category>sqlpath</category><category>postings</category><category>community</category><category>FILE_PKG</category><category>tabellenkalkulation</category><category>hamburg</category><category>tokenizer</category><category>array</category><category>truncate</category><category>Job</category><category>SIMPLE_INTEGER</category><category>dbms_file_transfer</category><category>with</category><category>best db project</category><category>odci</category><category>message</category><category>rss</category><category>11g</category><category>like</category><category>inhalt</category><category>gleichung</category><category>wget</category><category>start with</category><category>plsql</category><category>transactional</category><category>table</category><category>regexp_replace</category><category>foreign key</category><category>type</category><category>workshop</category><category>Geodaten</category><category>textbasiert</category><category>group by</category><category>authentication</category><category>webservices</category><category>commit</category><category>connect by</category><category>ols_regression</category><category>where</category><category>analytic function</category><category>inventory</category><category>Session</category><category>diff</category><category>getpivotsql</category><category>xmldiff</category><category>beta</category><category>c</category><category>objektrelational</category><category>oerr</category><category>SDO_GEOM</category><category>report</category><category>bytes</category><category>alert</category><category>instead-of</category><category>dml</category><category>view</category><category>UTL_SMTP</category><category>treffen</category><category>to_char</category><category>network</category><category>external</category><category>datetime</category><category>error</category><category>sysman</category><category>UTL_HTTP</category><category>düsseldorf</category><category>securefiles</category><category>NUMBER</category><category>veranstaltung</category><category>berlin</category><category>space</category><category>DBMS_ACL_ADMIN</category><category>Betriebssystem</category><category>java mail</category><category>MAIL_CLIENT</category><category>magic</category><category>BINARY_FLOART</category><category>recursive</category><category>doag</category><category>import</category><category>ctx_doc</category><category>quote</category><category>xmlpatch</category><category>event</category><category>dump</category><category>gqlplus</category><category>sql developer</category><category>tracing</category><category>identifiers</category><category>sleep</category><category>Shell</category><category>drop</category><category>add_months</category><category>DBMS_CQ_NOTIFICATION</category><category>apex_util</category><category>enterprise manager</category><category>xml db</category><category>response</category><category>entwickler</category><category>bulk</category><category>lookup</category><category>xdb</category><category>xmltable</category><category>tuning</category><category>apex 4.0 plugins</category><category>rollen</category><category>remote database</category><category>update</category><category>repository</category><category>v$sesstat</category><category>dwh</category><category>time zone</category><category>dburi</category><category>tracefile</category><category>unique</category><category>extensions</category><category>login</category><category>cloud computing</category><category>11.2</category><category>ref</category><category>dbms_lock</category><category>dba</category><category>dbms_shared_pool</category><category>FILE_TYPE</category><category>size</category><category>Skript</category><category>version</category><category>sqldeveloper</category><category>ordvideo</category><category>select as of</category><category>DBMS_PREPROCESSOR</category><category>BINARY_DOUBLE</category><category>SQL*Plus</category><category>create</category><category>replace</category><category>v$session</category><category>DBMS_LDAP</category><category>unload</category><category>sql</category><category>twitter</category><category>index</category><category>bind variablen</category><category>updatable</category><category>md5</category><category>Kreuztabelle</category><category>dbms_xplan</category><category>os_command</category><category>unzip</category><category>ftp</category><category>privilegien</category><category>virtual Column</category><category>datafile</category><category>SDO_GEOMETRY</category><category>execution plan</category><category>webseminar</category><category>NLS_SORT</category><category>DBMS_SPACE</category><category>initialize</category><category>NLS_COMP</category><category>encoding</category><category>oradb</category><category>etl</category><category>sys_guid</category><category>storage</category><category>stammtisch</category><category>sqlplus</category><category>date</category><category>insert</category><category>CLOB</category><category>pl/scope</category><category>kalender</category><category>product</category><category>utl_i18n</category><category>regression</category><category>hint</category><category>dba_segments</category><category>cursor</category><category>table functions</category><category>publish</category><category>daten</category><category>11gr2</category><category>installer</category><category>servlet</category><category>scp</category><category>performance</category><category>group</category><category>vortrag</category><category>reverse</category><category>Oracle11g</category><category>xml</category><category>LOB</category><category>statistic</category><category>UTL_TCP</category><category>security</category><category>mtag</category><category>sequence</category><category>dbms_alert</category><category>optimizer</category><category>resumable</category><category>oracle414</category><category>httpuritype</category><category>user</category><category>query rewrite</category><category>filter</category><category>STRUCT</category><category>entwicklung</category><category>data_only</category><category>software</category><category>segment</category><category>odd</category><category>html</category><category>sig</category><category>regular expressions</category><category>request</category><category>linguistisch</category><category>binary xml</category><category>Datentyp</category><category>DBMS_XDB</category><category>münchen</category><category>dbms_assert</category><category>proxy</category><category>jdbc</category><category>debugging</category><category>tkprof</category><category>sql/xml</category><category>IN clause</category><category>map</category><category>change</category><category>dbms_datapump</category><category>extractvalue</category><category>load</category><category>pivot</category><category>orawsv</category><category>directory</category><category>export</category><category>Spatial</category><category>http</category><category>sql injection</category><category>muniqsoft</category><category>string</category><category>umlaut</category><category>having</category><category>download</category><category>delete</category><category>dbms_metadata</category><category>transactions</category><category>ORACLE_HOME</category><category>regexp_like</category><category>Function</category><category>browser</category><category>script</category><category>windows</category><category>data cartridge</category><category>aggregat</category><category>timestamp</category><category>csv</category><category>flashback</category><category>intelligent cursor sharing</category><category>explain plan</category><category>BLOB</category><category>database</category><category>merge</category><category>memory leak</category><category>release 2</category><category>nlssort</category><category>konferenz</category><category>soap</category><category>primary key</category><category>Umgebungsvariablen</category><category>sure</category><category>otn</category><category>Thread</category><category>relational</category><category>convert</category><category>DBMS_LOB</category><category>document</category><category>objects</category><category>trigger</category><category>2010</category><category>datenbank</category><category>force</category><category>ratio_to_report</category><category>jvm</category><category>Java</category><category>Datei</category><category>constraint</category><category>null</category><category>asm</category><category>dbms_flashback</category><category>stock quote</category><category>arithmetic</category><category>matrix</category><category>imap</category><category>DBMS_CONNECTION_POOL</category><category>Metadaten</category><category>DBMS_APPLICATION_INFO</category><category>dictionary</category><category>LONGOPS</category><category>tablespace</category><category>model</category><category>dbms_advanced_rewrite</category><category>UTL_FILE</category><category>pldoc</category><category>data</category><category>oraclexe</category><category>iana</category><category>password</category><category>boolean</category><category>zip</category><category>Compile</category><category>checksum</category><category>deferred</category><title>Oracle SQL und PL/SQL ...</title><description>Tipps, Tricks, "Best Practice"</description><link>http://sql-plsql-de.blogspot.com/</link><managingEditor>noreply@blogger.com (Carsten Czarski)</managingEditor><generator>Blogger</generator><openSearch:totalResults>191</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SqlUndPlsqlInOracle" /><feedburner:info uri="sqlundplsqlinoracle" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>48.1800773</geo:lat><geo:long>11.536734</geo:long><feedburner:emailServiceId>SqlUndPlsqlInOracle</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-5198384973810678333</guid><pubDate>Wed, 09 May 2012 08:12:00 +0000</pubDate><atom:updated>2012-05-09T09:12:24.390+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">http</category><category domain="http://www.blogger.com/atom/ns#">xdb</category><category domain="http://www.blogger.com/atom/ns#">plsql</category><category domain="http://www.blogger.com/atom/ns#">response</category><category domain="http://www.blogger.com/atom/ns#">soap</category><category domain="http://www.blogger.com/atom/ns#">orawsv</category><category domain="http://www.blogger.com/atom/ns#">request</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">webservices</category><title>SOAP-Zugang zu PL/SQL: Database Native Webservices</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;SOAP access to PL/SQL objects: Database Native Webservices &lt;/div&gt;
&lt;div lang="de"&gt;
&lt;p&gt;
 Heute möchte ich etwas über die &lt;i&gt;Database Native Webservices&lt;/i&gt; schreiben, die zwar 
 bereits mit der Datenbankversion 11g Release 1 eingeführt wurden, die aber immer noch kaum bekannt sind.
 Worum geht es? Mit den Database Native Webservices kann eine SQL-Query oder PL/SQL-Funktion
 ohne weiteren Aufwand als &lt;i&gt;SOAP-Style Webservice&lt;/i&gt; bereitgestellt werden. Und das geht so:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zunächst muss die &lt;b&gt;XML DB&lt;/b&gt; in der Datenbank vorhanden sein. Das prüft man am einfachsten
    mit einer Abfrage auf die View &lt;b&gt;DBA_REGISTRY&lt;/b&gt;.
    &lt;pre&gt;
select comp_id, version from dba_registry where comp_id='XML'

COMP_ID                        VERSION
------------------------------ ---------------------
XML                            11.2.0.2.0
&lt;/pre&gt; 
    Wenn hier keine Zeile zurückgegeben wird, ist die XML DB nicht vorhanden und
    es können auch keine Native Webservices genutzt werden. Mit dem PL/SQL Skript
    &lt;b&gt;catqm.sql&lt;/b&gt; in &lt;b&gt;$ORACLE_HOME/rdbms/admin&lt;/b&gt; kann die XML DB nachinstalliert werden.
&lt;/li&gt;
&lt;li&gt;
 Der &lt;i&gt;HTTP-Protokollserver&lt;/i&gt; der XML DB muss aktiviert sein. Normalerweise sind die FTP- und HTTP-Protokollserver
 deaktiviert. Nutzer des &lt;i&gt;Embedded PL/SQL Gateway&lt;/i&gt; auf OracleXE arbeiten typischerweise mit
 bereits aktiviertem HTTP-Protokollserver, denn der wird hier für APEX genutzt. Wenn Ihr nicht 
 auf OracleXE arbeitet oder euch generell nicht sicher seid, ob der HTTP-Protokollserver aktiv
 ist, könnt Ihr das mit einem &lt;b&gt;lsnrctl status&lt;/b&gt; nachprüfen:
&lt;pre&gt;
$ lsnrctl status

LSNRCTL for Linux: Version 11.2.0.2.0 - Production on 04-MAY-2012 10:58:27

Copyright (c) 1991, 2010, Oracle.  All rights reserved.
:
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=sccloud030.de.oracle.com)(PORT=1521)))
  &lt;span style="color: red"&gt;(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=sccloud030.de.oracle.com)(PORT=8080))(Presentation=HTTP)(Session=RAW))&lt;/span&gt;
:
Services Summary...
&lt;/pre&gt;
Ist diese Zeile nicht vorhanden, so ist der Protokollserver inaktiv. Dann aktiviert Ihr ihn einfach
(als DBA) wie folgt. Verwendet nach Möglichkeit einen TCP/IP-Port über 1024. Für die Portnummern darunter
muss auf UNIX-Systemen der Listener besonders eingerichtet werden.
&lt;pre&gt;
begin
  dbms_xdb.sethttport({&lt;i&gt;http-port&lt;/i&gt;});
end;
&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;Die Database Native Webservices müssen (einmalig) innerhalb der XML DB aktiviert werden. Hierzu
    muss (als DBA) folgendes SQL-Kommando abgesetzt werden:
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;DECLARE&lt;/b&gt;&lt;/font&gt;
  SERVLET_NAME &lt;font color="#2e8b57"&gt;&lt;b&gt;VARCHAR2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;32&lt;/font&gt;) &lt;font color="#804040"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'orawsv'&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;BEGIN&lt;/b&gt;&lt;/font&gt;
  DBMS_XDB.deleteServletMapping(SERVLET_NAME);
  DBMS_XDB.deleteServlet(SERVLET_NAME);
  DBMS_XDB.addServlet(
    &lt;font color="#804040"&gt;&lt;b&gt;NAME&lt;/b&gt;&lt;/font&gt;     &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; SERVLET_NAME,
    &lt;font color="#804040"&gt;&lt;b&gt;LANGUAGE&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'C'&lt;/font&gt;,
    DISPNAME &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'Oracle Query Web Service'&lt;/font&gt;,
    DESCRIPT &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'Servlet for issuing queries as a Web Service'&lt;/font&gt;,
    &lt;font color="#008080"&gt;SCHEMA&lt;/font&gt;   &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'XDB'&lt;/font&gt;
  );
  DBMS_XDB.addServletSecRole(
    SERVNAME &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; SERVLET_NAME,
    ROLENAME &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'XDB_WEBSERVICES'&lt;/font&gt;,
    ROLELINK &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'XDB_WEBSERVICES'&lt;/font&gt;
  );
  DBMS_XDB.addServletMapping(
    PATTERN &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'/orawsv/*'&lt;/font&gt;,
    &lt;font color="#804040"&gt;&lt;b&gt;NAME&lt;/b&gt;&lt;/font&gt;    &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; SERVLET_NAME
  );
&lt;font color="#804040"&gt;&lt;b&gt;END&lt;/b&gt;&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
 Damit sind die datenbankweiten Vorbereitungen erledigt. Zum Ausprobieren können wir den Datenbankuser
 &lt;b&gt;SCOTT&lt;/b&gt; hernehmen. Zuerst bauen wir eine kleine PL/SQL-Funktion wie folgt:
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;replace&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/font&gt; get_sal(
  p_empno &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; emp.empno&lt;font color="#2e8b57"&gt;&lt;b&gt;%type&lt;/b&gt;&lt;/font&gt;
) &lt;font color="#804040"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt; emp.sal&lt;font color="#2e8b57"&gt;&lt;b&gt;%type&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/font&gt;
  l_sal emp.sal&lt;font color="#2e8b57"&gt;&lt;b&gt;%type&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/font&gt;
  &lt;font color="#804040"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;select&lt;/font&gt; sal &lt;font color="#008080"&gt;into&lt;/font&gt; l_sal &lt;font color="#008080"&gt;from&lt;/font&gt; emp &lt;font color="#008080"&gt;where&lt;/font&gt; empno &lt;font color="#804040"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt; p_empno;
  &lt;font color="#804040"&gt;&lt;b&gt;exception&lt;/b&gt;&lt;/font&gt;
    &lt;font color="#804040"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;no_data_found&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
    &lt;font color="#804040"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;others&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;raise&lt;/b&gt;&lt;/font&gt;;
  &lt;font color="#804040"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/font&gt;;
  &lt;font color="#804040"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt; l_sal;
&lt;font color="#804040"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/font&gt;;
&lt;/pre&gt;
&lt;p&gt;
 Diese Funktion &lt;b&gt;GET_SAL&lt;/b&gt; wollen wir nun als Native WebService aufrufen. Die Datenbank ist soweit vorbereitet. 
 Allerdings kann man nicht mit  jedem Datenbankuser einfach so Webservices aufrufen - es sind Rollen
 nötig. Für Database Native Webservices gibt es dero drei:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;XDB_WEBSERVICES&lt;/b&gt;: Ein Datenbankbankuser, der diese Rolle hat, ist prinzipiell in der Lage, PL/SQL Objekte und SQL-Abfragen als SOAP-Webservices auszuführen.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;XDB_WEBSERVICES_OVER_HTTP&lt;/b&gt;: Der Datenbankuser kann die Webservices mit dieser Rolle auch über ungesichertes HTTP aufrufen - es wird dann also &lt;i&gt;kein&lt;/i&gt; HTTPS benötigt. Ohne dieses Privileg wird der Webservice-Call nur über SSL erlaubt.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP_WEBSERVICES_WITH_PUBLIC&lt;/b&gt;: Der Datenbankuser  kann auch auf Objekte zugreifen, die "nur" über einen
    "Public" Grant bereitstehen. Ohne diese Rolle muss der Datenbankuser Eigentümer der Objekte sein oder
    explizite Privilegien haben.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
 Also bekommt unser Datenbankuser &lt;b&gt;SCOTT&lt;/b&gt; zwei Privilegien:
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;grant&lt;/font&gt; xdb_webservices &lt;font color="#008080"&gt;to&lt;/font&gt; scott
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

&lt;font color="#008080"&gt;grant&lt;/font&gt; xdb_webservices_over_http &lt;font color="#008080"&gt;to&lt;/font&gt; scott
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 Damit sind alle Vorbereitungen gemacht. Um einen Webservice per SOAP aufrufen zu können, braucht es
 das WSDL-Dokument, also die "Schnittstellenbeschreibung" für den Web Service. Die Database Native 
 Webservices generieren dieses automatisch. Probiert im Browser einfach folgende URL aus:
&lt;/p&gt;
&lt;p&gt;
 &lt;code&gt;&lt;b&gt;http://{host}:{port}/&lt;span style="color: red"&gt;orawsv/&lt;/span&gt;&lt;span style="color: blue"&gt;SCOTT/GET_SAL&lt;/span&gt;?wsdl&lt;/b&gt;&lt;/code&gt;
&lt;/p&gt;
&lt;p&gt;Im Browser werdet Ihr dann zuerst nach Usernamen und Passwort gefragt. Hier loggt Ihr euch mit
   SCOTT und seinem Passwort ein. Wichtig ist: Der Login muss mit dem Datenbankaccount erfolgen,
   welcher die XDB_WEBSERVICES-Rollen hat - es muss nicht zwingend der Eigentümer der aufgerufenen
   Funktion sein. Nach dem Login zeigt euch der Browser das WSDL-Dokument für den Webservice an.
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-bLJo1Lfsg6Y/T6e3Q4HqNDI/AAAAAAAAAKo/YQPgSUyA5Fs/s1600/wsdl-ie.png" imageanchor="1" style=""&gt;&lt;img border="0" height="206" width="320" src="http://3.bp.blogspot.com/-bLJo1Lfsg6Y/T6e3Q4HqNDI/AAAAAAAAAKo/YQPgSUyA5Fs/s320/wsdl-ie.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
  Mit Hilfe
  dieser URL kann nun jeder SOAP-Client mit der Datenbankfunktion &lt;b&gt;GET_SAL&lt;/b&gt; arbeiten. Der folgende
  Screenshot zeigt ein Beispiel - typischerweise wird zunächst die URL zum WSDL-Dokument angegeben; das
  Werkzeug liest danach die Informationen aus und generiert einen &lt;i&gt;SOAP-Request&lt;/i&gt; als Vorlage. Dort
  kann man dann eine der EMPNOs aus der Tabelle &lt;b&gt;EMP&lt;/b&gt; eintragen und den Request zum Server senden - die
  Antwort kommt wiederum als &lt;i&gt;SOAP-Response&lt;/i&gt;. 
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-tdeOHkO04Do/T6e3QWNTTFI/AAAAAAAAAKc/NQJAxhEwMdo/s1600/test-ws.png" imageanchor="1" style=""&gt;&lt;img border="0" height="199" width="320" src="http://2.bp.blogspot.com/-tdeOHkO04Do/T6e3QWNTTFI/AAAAAAAAAKc/NQJAxhEwMdo/s320/test-ws.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
   Hier habe ich noch einen Screenshot aus Application
   Express - es ist zwar eine seltsame Idee, eine PL/SQL-Funktion aus APEX heraus per Webservice-Schnittstelle
   aufzurufen, aber es funktioniert.
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-acbG0id_orI/T6e3RBCkzJI/AAAAAAAAAK0/CB14EGL4j6E/s1600/wsdl-ws-apex.png" imageanchor="1" style=""&gt;&lt;img border="0" height="170" width="320" src="http://2.bp.blogspot.com/-acbG0id_orI/T6e3RBCkzJI/AAAAAAAAAK0/CB14EGL4j6E/s320/wsdl-ws-apex.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
 Es ist also sehr einfach, eine PL/SQL-Funktion oder SQL-Query als SOAP-Webservice verfügbar zu
 machen - ein paar Dinge gibt es aber noch zu sagen:
&lt;/p&gt;
&lt;p&gt;
 Die oben genannten Privilegien erlauben zunächst keine feingranulare Steuerung, welche
 PL/SQL-Funktionen oder -Prozeduren als Web Service verfügbar gemacht werden sollen. Man vergibt
 nur die Rollen an einen Datenbankuser - und alle Objekte, die diesem User gehören, können dann
 als Web Service aufgerufen werden. Das scheint erstmal sehr grob - aber nur auf den ersten Blick.
 Denn die XDB_WEBSERVICES-Rollen solle man &lt;i&gt;niemals&lt;/i&gt; dem Eigentümer der Objekte geben. Vielmehr
 sollte man einen eigenen "Webservice-Connect-User" einrichten - dieser bekommt eine "Minimalausstattung"
 an Privilegien ...
&lt;/p&gt;
&lt;pre&gt;
create user webservice_connect identified by {password};

grant create session to webservice_connect;
grant xdb_webservices to webservice_connect;
grant xdb_webservices_over_http to webservice_connect;
&lt;/pre&gt;
&lt;p&gt;
 Und an diesen User werden nun die EXECUTE-Rechte an den PL/SQL-Objekten, die man als Webservice
 bereitstellen möchte, &lt;i&gt;explizit&lt;/i&gt; und &lt;i&gt;einzeln&lt;/i&gt; vergeben. Als &lt;b&gt;SCOTT&lt;/b&gt; wird also folgendes
 ausgeführt ...
&lt;/p&gt;
&lt;pre&gt;
grant execute on scott.get_sal to webservice_connect;
&lt;/pre&gt;
&lt;p&gt;
 Zum Abrufen des WSDL wird nun die &lt;i&gt;gleiche&lt;/i&gt; URL verwendet, wie vorhin; der Login muss
 allerdings nun als &lt;b&gt;WEBSERVICE_CONNECT&lt;/b&gt; erfolgen und nicht mehr als &lt;b&gt;SCOTT&lt;/b&gt;. Das WSDL wird danach
 ganz genauso aussehen und der Webservice lässt sich auch genauso nutzen - nur kann man nun
 auf Objektebene festlegen, welche Funktionen und Prozeduren als Webservice bereitstehen. Eben nur
 diejenigen, an denen &lt;b&gt;WEBSERVICE_CONNECT&lt;/b&gt; Rechte hat.
&lt;/p&gt;
&lt;p&gt;
 Packages können auf den ersten Blick nur als Ganzes freigegeben werden - das ist zunächst auch
 richtig. Auch mit einem Grant des Execute-Privilegs an WEBSERVICE_CONNECT wird das ganze Package
 freigeschaltet. Allerdings würde ich für ein Webservice-Szenario ein eigenes "Wrapper-Paket" schreiben,
 welches nur die für den Webservice freigegebene Schnittstelle enthält. Hier kann man auch gleich
 PL/SQL-eigene Datentypen wie &lt;b&gt;boolean&lt;/b&gt; und &lt;b&gt;record&lt;/b&gt;, die von den Native Webservices nicht
 unterstützt werden, auf SQL-Typen abbilden.
&lt;/p&gt;
&lt;p&gt;
 Möchte man nicht nur einen skalaren Datentypen (wie NUMBER oder VARCHAR2), sondern ein ganzes
 Objekt als Parameter übergeben, so
 können Objekttypen eingesetzt werden. Objekttypen können als Input- oder als Output-Parameter verwendet
 werden. Eine Funktion &lt;b&gt;CREATE_EMP&lt;/b&gt; könnte dann so aussehen ... 
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; emp_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; object(
 EMPNO      &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4&lt;/font&gt;),
 ENAME      &lt;font color="#2e8b57"&gt;&lt;b&gt;VARCHAR2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;10&lt;/font&gt;),
 JOB        &lt;font color="#2e8b57"&gt;&lt;b&gt;VARCHAR2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;9&lt;/font&gt;),
 MGR        &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4&lt;/font&gt;),
 HIREDATE   &lt;font color="#2e8b57"&gt;&lt;b&gt;DATE&lt;/b&gt;&lt;/font&gt;,
 SAL        &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;7&lt;/font&gt;,&lt;font color="#ff00ff"&gt;2&lt;/font&gt;),
 COMM       &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;7&lt;/font&gt;,&lt;font color="#ff00ff"&gt;2&lt;/font&gt;),
 DEPTNO     &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;2&lt;/font&gt;)
)
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;procedure&lt;/font&gt; create_emp(
  p_emp emp_t 
) &lt;font color="#6a5acd"&gt;as&lt;/font&gt;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
 :
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/
&lt;/pre&gt;
&lt;p&gt;
 Hierzu lässt sich wiederum direkt ein WSDL abrufen (wie oben). Und der Objekttyp &lt;b&gt;EMP_T&lt;/b&gt; wird
 hier auch als komplexer XML-Datentyp erkannt ...
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;EMP_T&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;EMPNO&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;ENAME&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;base&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:string&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
            &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;maxLength&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;value&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;10&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;JOB&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;base&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:string&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
            &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;maxLength&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;value&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;9&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;MGR&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;HIREDATE&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:date&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;SAL&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;COMM&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;DEPTNO&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&amp;gt;&lt;/font&gt;
&lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 Auch Arrays (VARRAY oder Nested Table-Types) können verwendet werden, aber nicht auf "oberster" Ebene. So
 führt folgendes bereits beim Versuch, das WSDL abzurufen, zu einer Fehlermeldung:
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; varchar_table_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#6a5acd"&gt;table&lt;/font&gt; &lt;font color="#6a5acd"&gt;of&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4000&lt;/font&gt;)
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;procedure&lt;/font&gt; my_func(
  p_vtab varchar_table_t 
) &lt;font color="#6a5acd"&gt;as&lt;/font&gt;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
 :
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/
&lt;/pre&gt;
&lt;p&gt;
 Die Lösung ist einfach: Auf der obersten Ebene (also als Funktionsparamater) darf kein
 VARRAY oder TABLE-Typ verwendet werden. Es ist aber durchaus erlaubt, solche in einem
 Objekttypen zu nutzen. Wir wandeln das Beispiel also ein wenig um ...
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; varchar_table_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#6a5acd"&gt;table&lt;/font&gt; &lt;font color="#6a5acd"&gt;of&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4000&lt;/font&gt;)
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; param_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; object(
  varchar_table varchar_table_t
);
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;procedure&lt;/font&gt; my_func(
  p_vtab param_t 
) &lt;font color="#6a5acd"&gt;as&lt;/font&gt;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
  :
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/
&lt;/pre&gt;
&lt;p&gt;
 Nun wird das WSDL korrekt generiert und der Webservice kann verwendet werden. Hier der Auszug aus
 dem WSDL, welcher den komplexen Typ &lt;span class="boldbodycopy"&gt;PARAM_T&lt;/span&gt; beschreibt.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;PARAM_T&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;VARCHAR_TABLE&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
            &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;VARCHAR2&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:string&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;maxOccurs&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;unbounded&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;minOccurs&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;0&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&amp;gt;&lt;/font&gt;
&lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
Alles in allem sind die Native Webservices ein sehr eleganter und einfacher Weg, SQL-Abfragen und PL/SQL-Objekte
als SOAP-Style Webservices im Unternehmen bereitzustellen. Macht man es mit Java- oder .NET-Mitteln, muss hierfür
meist aufwändig Code geschrieben werden. Mehr dazu findet Ihr in der Oracle-Dokumentation:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://docs.oracle.com/cd/E11882_01/appdev.112/e23094/xdb_web_services.htm#CHDDBCHB"
   target="_blank"&gt;Oracle XML DB Developers' Guide: 33 Using Native Oracle XML DB Web Services&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;










&lt;div lang="en" style="display: none;"&gt;
&lt;p&gt;
 This blog posting is about &lt;i&gt;Database native webservices&lt;/i&gt;; a feature, which was introduced
 with Oracle11g Release 1 (11.1). Database Native Webservices allow to publish a SQL Query or
 a PL/SQL unit (Function, Procedure, Package) as a &lt;i&gt;SOAP Style Webservice&lt;/i&gt; &lt;b&gt;without
 additional programming&lt;/b&gt;. 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
 Database native Webservices are Part of the XML DB functionaliry. So make sure that XML DB
 is part of your database. The dictionary view DBA_REGISTRY allows to check this:
    &lt;pre&gt;
select comp_id, version from dba_registry where comp_id='XML'

COMP_ID                        VERSION
------------------------------ ---------------------
XML                            11.2.0.2.0
&lt;/pre&gt; 
  If this query returns no rows, then XML DB is not installed in your database - and you
  cannot use the webservice feature. XML DB can be installed into an existing database
  by starting the SQL script &lt;b&gt;catqm.sql&lt;/b&gt; in &lt;b&gt;$ORACLE_HOME/rdbms/admin&lt;/b&gt;. Of course, this must
  be done by a DBA.
&lt;/li&gt;
&lt;li&gt;
 Nou need the XML DB protocol server for HTTP being activated. After a normal database 
 creation these are disabled by default. OracleXE users probably will have an activated
 HTTP protocol server on port 8080 (it is being used for working with APEX). If you are 
 not sure, simply check on the database server with the &lt;b&gt;lsnrctl status&lt;/b&gt; command.
&lt;/li&gt;
&lt;pre&gt;
$ lsnrctl status

LSNRCTL for Linux: Version 11.2.0.2.0 - Production on 04-MAY-2012 10:58:27

Copyright (c) 1991, 2010, Oracle.  All rights reserved.
:
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=sccloud030.de.oracle.com)(PORT=1521)))
  &lt;span style="color: red"&gt;(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=sccloud030.de.oracle.com)(PORT=8080))(Presentation=HTTP)(Session=RAW))&lt;/span&gt;
:
Services Summary...
&lt;/pre&gt;
  If the red line is not present, the HTTP protocol server is disabled. It needs to be
  enabled with the following command (again: you need DBA privileges, at least the 
  &lt;b&gt;XDBADMIN&lt;/b&gt; role). On Linux or Unix systems choose a TCP/IP port above 1024; ports
  below require additional listener configuration.
&lt;pre&gt;
begin
  dbms_xdb.sethttport({&lt;i&gt;http-port&lt;/i&gt;});
end;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
 Now, having XML DB present and the protocol server enabled, you need to enable the
 webservice feature as such. The following command needs to be executed once - again
 with DBA privileges or the &lt;b&gt;XDBADMIN&lt;/b&gt; role.
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;DECLARE&lt;/b&gt;&lt;/font&gt;
  SERVLET_NAME &lt;font color="#2e8b57"&gt;&lt;b&gt;VARCHAR2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;32&lt;/font&gt;) &lt;font color="#804040"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'orawsv'&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;BEGIN&lt;/b&gt;&lt;/font&gt;
  DBMS_XDB.deleteServletMapping(SERVLET_NAME);
  DBMS_XDB.deleteServlet(SERVLET_NAME);
  DBMS_XDB.addServlet(
    &lt;font color="#804040"&gt;&lt;b&gt;NAME&lt;/b&gt;&lt;/font&gt;     &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; SERVLET_NAME,
    &lt;font color="#804040"&gt;&lt;b&gt;LANGUAGE&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'C'&lt;/font&gt;,
    DISPNAME &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'Oracle Query Web Service'&lt;/font&gt;,
    DESCRIPT &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'Servlet for issuing queries as a Web Service'&lt;/font&gt;,
    &lt;font color="#008080"&gt;SCHEMA&lt;/font&gt;   &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'XDB'&lt;/font&gt;
  );
  DBMS_XDB.addServletSecRole(
    SERVNAME &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; SERVLET_NAME,
    ROLENAME &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'XDB_WEBSERVICES'&lt;/font&gt;,
    ROLELINK &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'XDB_WEBSERVICES'&lt;/font&gt;
  );
  DBMS_XDB.addServletMapping(
    PATTERN &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'/orawsv/*'&lt;/font&gt;,
    &lt;font color="#804040"&gt;&lt;b&gt;NAME&lt;/b&gt;&lt;/font&gt;    &lt;font color="#804040"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt; SERVLET_NAME
  );
&lt;font color="#804040"&gt;&lt;b&gt;END&lt;/b&gt;&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
 Now the database is ready to provide &lt;i&gt;database native webservices&lt;/i&gt;. For testing we use a plain
 database account (say: &lt;b&gt;SCOTT&lt;/b&gt;). First we create a little PL/SQL function as follows ...
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;replace&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/font&gt; get_sal(
  p_empno &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; emp.empno&lt;font color="#2e8b57"&gt;&lt;b&gt;%type&lt;/b&gt;&lt;/font&gt;
) &lt;font color="#804040"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt; emp.sal&lt;font color="#2e8b57"&gt;&lt;b&gt;%type&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/font&gt;
  l_sal emp.sal&lt;font color="#2e8b57"&gt;&lt;b&gt;%type&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/font&gt;
  &lt;font color="#804040"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;select&lt;/font&gt; sal &lt;font color="#008080"&gt;into&lt;/font&gt; l_sal &lt;font color="#008080"&gt;from&lt;/font&gt; emp &lt;font color="#008080"&gt;where&lt;/font&gt; empno &lt;font color="#804040"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt; p_empno;
  &lt;font color="#804040"&gt;&lt;b&gt;exception&lt;/b&gt;&lt;/font&gt;
    &lt;font color="#804040"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;no_data_found&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
    &lt;font color="#804040"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;others&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;raise&lt;/b&gt;&lt;/font&gt;;
  &lt;font color="#804040"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/font&gt;;
  &lt;font color="#804040"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt; l_sal;
&lt;font color="#804040"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/font&gt;;
&lt;/pre&gt;
&lt;p&gt;
 This function GET_SAL will now be executed as a native web service. The database has been prepared and
 the function is ready. Before actually doing it, we need some privileges (of course, this feature
 is being protected). There are three different roles.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;XDB_WEBSERVICES&lt;/b&gt;: This role enables the database native web service feature in general. A user having
 this role can access own objects and objects with &lt;i&gt;explicit&lt;/i&gt; privileges as SOAP style webservices. But for
 our test we will also need the next role.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;XDB_WEBSERVICES_OVER_HTTP&lt;/b&gt;: With this role, the database user can access his webservices also over "plain" HTTP, i.e. SSL communication is not required. Without this role, webservice calls only work over HTTPS (the protocol server must be configured for HTTPS in that case).&lt;/li&gt;.
&lt;li&gt;&lt;b&gt;HTTP_WEBSERVICES_WITH_PUBLIC&lt;/b&gt;: This role enables also executing public objects as web services. Without it, only own objects and objects with explicit privileges can be accessed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
 So our database user &lt;b&gt;SCOTT&lt;/b&gt; gets two additional roles ...
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;grant&lt;/font&gt; xdb_webservices &lt;font color="#008080"&gt;to&lt;/font&gt; scott
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

&lt;font color="#008080"&gt;grant&lt;/font&gt; xdb_webservices_over_http &lt;font color="#008080"&gt;to&lt;/font&gt; scott
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 Now &lt;i&gt;all&lt;/i&gt; requirements are met. The first thing a client needs in order to call the web 
 service, is the WSDL document. The WSDL is the interface description in XML format. It contains
 information about the name of the webservice, its input and output parameters and so on. The 
 Oracle database generates the WSDL automatically. Just open your browser and visit the 
 URL as follows ... 
&lt;/p&gt;
&lt;p&gt;
 &lt;code&gt;&lt;b&gt;http://{database-host}:{http-port}/&lt;span style="color: red"&gt;orawsv/&lt;/span&gt;&lt;span style="color: blue"&gt;SCOTT/GET_SAL&lt;/span&gt;?wsdl&lt;/b&gt;&lt;/code&gt;
&lt;/p&gt;
&lt;p&gt;
 The browser not prompts you for username and password. Log in as wou would do in SQL*Plus. Keep in mind
 that you need the credentials of the database user having the XDB_WEBSERVICES roles. The object owner
 might be different. After logging in you'll see the WSDL as follows ...
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-bLJo1Lfsg6Y/T6e3Q4HqNDI/AAAAAAAAAKo/YQPgSUyA5Fs/s1600/wsdl-ie.png" imageanchor="1" style=""&gt;&lt;img border="0" height="206" width="320" src="http://3.bp.blogspot.com/-bLJo1Lfsg6Y/T6e3Q4HqNDI/AAAAAAAAAKo/YQPgSUyA5Fs/s320/wsdl-ie.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
 Having that URL every SOAP client can call the PL/SQL function as a web service. Following you'll 
 see some screen shots. The flow of operation is basically the same for all client: First, get the
 WSDL from the database, then send a SOAP request (which can be generated from the WSDL) and then
 receive the SOAP response. How each step is being performed, depends on the SOAP client you are
 actually using. The second screen shot is from Oracle Application Express (which also has 
 a webservice interface). 
&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-tdeOHkO04Do/T6e3QWNTTFI/AAAAAAAAAKc/NQJAxhEwMdo/s1600/test-ws.png" imageanchor="1" style=""&gt;&lt;img border="0" height="199" width="320" src="http://2.bp.blogspot.com/-tdeOHkO04Do/T6e3QWNTTFI/AAAAAAAAAKc/NQJAxhEwMdo/s320/test-ws.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-acbG0id_orI/T6e3RBCkzJI/AAAAAAAAAK0/CB14EGL4j6E/s1600/wsdl-ws-apex.png" imageanchor="1" style=""&gt;&lt;img border="0" height="170" width="320" src="http://2.bp.blogspot.com/-acbG0id_orI/T6e3RBCkzJI/AAAAAAAAAK0/CB14EGL4j6E/s320/wsdl-ws-apex.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
 Looking at the mentioned &lt;b&gt;XDB_WEBSERVICES&lt;/b&gt; privileges it seems that only complete schemas can be
 enabled or disabled for webservices - the privileges can only be granted to database users. There
 is no PL/SQL package to work at the procedure or function level. But we can use standard database
 methods here. The &lt;b&gt;XDB_WEBSERVICES&lt;/b&gt; roles should &lt;i&gt;never&lt;/i&gt; be granted to the object owners directly. It's a
 better idea to create a separate "webservice connect user" with a limited set of privileges ...
&lt;/p&gt;
&lt;pre&gt;
create user webservice_connect identified by {password};

grant create session to webservice_connect;
grant xdb_webservices to webservice_connect;
grant xdb_webservices_over_http to webservice_connect;
&lt;/pre&gt;
&lt;p&gt;
 Then the object (functiom procedure) owner does &lt;i&gt;explicit&lt;/i&gt; and &lt;i&gt;individual&lt;/i&gt; grants 
 on the desired objects to the "webservice connect user". So, in our example, &lt;b&gt;SCOTT&lt;/b&gt; issues
 the following GRANT statements ...
&lt;/p&gt;
&lt;pre&gt;
grant execute on scott.get_sal to webservice_connect;
&lt;/pre&gt;
&lt;p&gt;
 We get the WSDL document we use &lt;i&gt;the same URL&lt;/i&gt; as previously. But when the browser prompts
 for a login, we don't use &lt;b&gt;SCOTT&lt;/b&gt; anymore - now we use the &lt;b&gt;WEBSERVICE_CONNECT&lt;/b&gt; user. If the grants
 have been implemented correctly, we can just execute the one procedure &lt;b&gt;SCOTT.GET_SAL&lt;/b&gt; as a
 native webservice.
&lt;/p&gt;
&lt;p&gt;
 When it's about packages there's a bit more of work to do: With the described approach we can 
 enable or disable web service access only at the package level. When webservice access is being
 enabled for a particular package, all public functions and procedures in that package can be 
 executed. If this should be limited to a reduced set of procedures and functions, we need a
 "wrapper package" on top of the functional one. The wrapper package contains just the functions
 and procedures to be enabled for webservice access. And execute privileges are then being
 granted on the wrapper package. Such a wrapper package can also be used to handle PL/SQL-only data
 types like &lt;b&gt;boolean&lt;/b&gt; or &lt;b&gt;record&lt;/b&gt; which are not supported by the webservice feature.
&lt;/p&gt;
&lt;p&gt;
 If object structures are needed as webservice arguments (in pure PL/SQL we might use records),
 then we need to create &lt;i&gt;Object Types&lt;/i&gt; for this. Object types can be used as input or output arguments.
 A function &lt;b&gt;CREATE_EMP&lt;/b&gt; with an object type argument could look like this:
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; emp_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; object(
 EMPNO      &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4&lt;/font&gt;),
 ENAME      &lt;font color="#2e8b57"&gt;&lt;b&gt;VARCHAR2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;10&lt;/font&gt;),
 JOB        &lt;font color="#2e8b57"&gt;&lt;b&gt;VARCHAR2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;9&lt;/font&gt;),
 MGR        &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4&lt;/font&gt;),
 HIREDATE   &lt;font color="#2e8b57"&gt;&lt;b&gt;DATE&lt;/b&gt;&lt;/font&gt;,
 SAL        &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;7&lt;/font&gt;,&lt;font color="#ff00ff"&gt;2&lt;/font&gt;),
 COMM       &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;7&lt;/font&gt;,&lt;font color="#ff00ff"&gt;2&lt;/font&gt;),
 DEPTNO     &lt;font color="#2e8b57"&gt;&lt;b&gt;NUMBER&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;2&lt;/font&gt;)
)
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;procedure&lt;/font&gt; create_emp(
  p_emp emp_t 
) &lt;font color="#6a5acd"&gt;as&lt;/font&gt;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
 :
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/
&lt;/pre&gt;
&lt;p&gt;
 Now we can -again- retrieve the WSDL using the URL &lt;b&gt;.../orawsv/SCOTT/GET_EMP?wsdl&lt;/b&gt;. Our 
 input argument has been detected and "translated" to an XML structure. A SOAP client will now
 be able to contruct a matching SOAP request. 
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;EMP_T&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;EMPNO&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;ENAME&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;base&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:string&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
            &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;maxLength&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;value&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;10&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;JOB&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;base&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:string&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
            &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;maxLength&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;value&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;9&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;restriction&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;simpleType&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;MGR&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;HIREDATE&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:date&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;SAL&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;COMM&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;DEPTNO&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:double&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&amp;gt;&lt;/font&gt;
&lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 We can also use VARRAY and nested table types to pass arrays or lists to the web service. But here 
 we have one restriction. VARRAY or NESTED table types cannot be used at the "top-level", directly
 as procedure or function arguments. The database would then not be able to generate a WSDL and the
 web service cannot be called. 
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; varchar_table_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#6a5acd"&gt;table&lt;/font&gt; &lt;font color="#6a5acd"&gt;of&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4000&lt;/font&gt;)
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;procedure&lt;/font&gt; my_func(
  p_vtab varchar_table_t 
) &lt;font color="#6a5acd"&gt;as&lt;/font&gt;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
 :
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/
&lt;/pre&gt;
&lt;p&gt;
 But there is a simple workaround: Just embed the VARRAY or table type
 into another object type - as illustrated in the following example:
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; varchar_table_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#6a5acd"&gt;table&lt;/font&gt; &lt;font color="#6a5acd"&gt;of&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;(&lt;font color="#ff00ff"&gt;4000&lt;/font&gt;)
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;type&lt;/font&gt; param_t &lt;font color="#6a5acd"&gt;as&lt;/font&gt; object(
  varchar_table varchar_table_t
);
/

&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;procedure&lt;/font&gt; my_func(
  p_vtab param_t 
) &lt;font color="#6a5acd"&gt;as&lt;/font&gt;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
  :
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/
&lt;/pre&gt;
&lt;p&gt;
 Now the WSDL can be generated and the webservice is callable again. Here is the WSDL part describing the
 input argument &lt;b&gt;PARAM_T&lt;/b&gt;.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;PARAM_T&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;VARCHAR_TABLE&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&lt;/font&gt;&lt;font color="#008080"&gt;&amp;gt;&lt;/font&gt;
            &lt;font color="#008080"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;VARCHAR2&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;type&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;xsd:string&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;maxOccurs&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;unbounded&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt; &lt;/font&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;minOccurs&lt;/b&gt;&lt;/font&gt;=&lt;font color="#ff00ff"&gt;&amp;quot;0&amp;quot;&lt;/font&gt;&lt;font color="#008080"&gt;/&amp;gt;&lt;/font&gt;
          &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&amp;gt;&lt;/font&gt;
        &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&amp;gt;&lt;/font&gt;
      &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
    &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;sequence&amp;gt;&lt;/font&gt;
  &lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;complexType&amp;gt;&lt;/font&gt;
&lt;font color="#008080"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#6a5acd"&gt;xsd&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#008080"&gt;element&amp;gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
As we have seen: It's very easy to publish PL/SQL objects as SOAP style webservices - just using the
onboard utilities of the Oracle database: All we have to do is to enable the feature once and to grant privileges. 
In advanced scenarios we'll need additional wrapper packages or optimized data types for the procedure arguments.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://docs.oracle.com/cd/E11882_01/appdev.112/e23094/xdb_web_services.htm#CHDDBCHB"
   target="_blank"&gt;Oracle XML DB Developers' Guide: 33 Using Native Oracle XML DB Web Services&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-5198384973810678333?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/WKt0iPGtMcQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/WKt0iPGtMcQ/soap-zugang-zu-plsql-database-native.html</link><author>noreply@blogger.com (Carsten Czarski)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-bLJo1Lfsg6Y/T6e3Q4HqNDI/AAAAAAAAAKo/YQPgSUyA5Fs/s72-c/wsdl-ie.png" height="72" width="72" /><thr:total>2</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1366069 11.5770851</georss:point><georss:box>47.967062399999996 11.2612281 48.3061514 11.892942099999999</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/05/soap-zugang-zu-plsql-database-native.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-7671008878807819467</guid><pubDate>Mon, 30 Apr 2012 08:57:00 +0000</pubDate><atom:updated>2012-04-30T09:57:00.643+01:00</atom:updated><title>Workshop zum Thema "Oracle TEXT": Mai 2012 in Düsseldorf und Stuttgart</title><description>&lt;div lang="en" style="display: none"&gt;
This blog posting is about an Oracle TEXT workshop in german language in therefore in German only.
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;p&gt;
 Das Thema "Suchen" ist beim Umgang mit SQL und PL/SQL allgegenwärtig. Sei es die Suche in Dokumenten, Kunden-, Produkt-, Lieferanten- oder Geschäftsstellendaten - immer wieder müssen Sachbearbeiter anhand eines Stichworts, eines Namens oder einer Nummer etwas finden. Folgerichtig statten Entwickler alle Formulare und Anwendungsseiten mit entsprechender Suchfunktionalität und entwickeln teilweise sehr ausgefallene Programmlogik zum Umsetzen der Suche aus. 
&lt;/p&gt;
&lt;p&gt;
 Die Oracle-Datenbank enthält &lt;b&gt;bereits in der Standard Edition Oracle TEXT&lt;/b&gt;. Dabei denken viele an die Suche in Dokumentbeständen, aber das ist noch nicht alles: Mit Oracle TEXT können Sie Ihrer Anwendung eine mächtige Suchfunktion hinzufügen - nicht nur auf Dokumente, sondern auch auf "normale" relationale Datenbestände. Ähnlichkeitssuche ist ebenso möglich wie die Suche über mehrere Tabellen hinweg. Im &lt;b&gt;Mai 2012 führen wir  in Düsseldorf und Stuttgart einen Workshop zum Thema Oracle TEXT&lt;/b&gt; durch. Dort habt
 Ihr Gelegenheit, mehr über die Möglichkeiten mit Oracle TEXT zu erfahren. Vormittags geben wir einen Überblick über Oracle TEXT, mögliche 
 Einsatzszenarien sowie Tipps &amp;amp; Tricks zum Umgang damit. Nachmittags widmen wir uns fortgeschrittenen Themen wie dem Monitoring, 
 Oracle TEXT-Indizes auf mehrere Tabellen, den verschiedenen Konfigurationsmöglichkeiten und einiges mehr. 
&lt;/p&gt;
&lt;p&gt;Die Agenda
&lt;/p&gt;
&lt;p&gt;
&lt;table border="0" cellpadding="3" cellspacing="4" style="border: 0.5pt solid black; margin-top: 3mm; max-width: 800px;"&gt;
   &lt;tbody&gt;
&lt;tr&gt;
     &lt;td colspan="2" rowspan="1" style="font-family: Helvetica,Arial,sans-serif;"&gt;10:00 Beginn der Veranstaltung 
     &lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;tr&gt;
     &lt;td style="width: 40px;"&gt;&lt;/td&gt;
     &lt;td style="background-color: #cccccc; padding: 2px;"&gt;&lt;div style="font-size: 10pt;"&gt;
&lt;b&gt;Oracle TEXT: Ein Überblick&lt;/b&gt; 
      &lt;/div&gt;
&lt;div style="margin-top: 3px;"&gt;
Konzepte und generelle Funktionsweise von Oracle TEXT, Einsatzszenarien
      &lt;/div&gt;
&lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;tr&gt;
     &lt;td style="width: 40px;"&gt;&lt;/td&gt;
     &lt;td style="background-color: #cccccc; padding: 2px;"&gt;&lt;div style="font-size: 10pt;"&gt;
&lt;b&gt;Umgang mit Oracle TEXT: Tipps &amp;amp; Tricks aus der Praxis&lt;/b&gt; 
      &lt;/div&gt;
&lt;div style="margin-top: 3px;"&gt;
Einblick in die Wartung eines Textindex, wie formuliert man Oracle TEXT Abfragen
       richtig?&lt;br /&gt;
Welche grundsätzlichen Möglichkeiten habe ich?
      &lt;/div&gt;
&lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;tr&gt;
     &lt;td colspan="2" rowspan="1" style="font-family: Helvetica,Arial,sans-serif;"&gt;Mittagspause
     &lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;tr&gt;
     &lt;td style="width: 40px;"&gt;&lt;/td&gt;
     &lt;td style="background-color: #cccccc; padding: 2px;"&gt;&lt;div style="font-size: 10pt;"&gt;
&lt;b&gt;Überwachung und Wartung eines Oracle Text Index im Detail&lt;/b&gt; 
     &lt;/div&gt;
&lt;div style="margin-top: 3px;"&gt;
Synchronisierungs- und Optimierungsintervalle, Strategien, Feststellung der Fragmentierung,&lt;br /&gt;
Hochverfügbarkeit mit Schattenindex-Technologie und mehr ...
      &lt;/div&gt;
&lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;tr&gt;
     &lt;td style="width: 40px;"&gt;&lt;/td&gt;
     &lt;td style="background-color: #cccccc; padding: 2px;"&gt;&lt;div style="font-size: 10pt;"&gt;
&lt;b&gt;"Textindex nach Art des Hauses": Konfiguration eines TEXT-Index &lt;/b&gt; 
     &lt;/div&gt;
&lt;div style="margin-top: 3px;"&gt;
Lexer-Einstellungen, Stopwortlisten, Umgang mit Umlauten, Thesaurus und mehr ...
      &lt;/div&gt;
&lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;tr&gt;
     &lt;td style="width: 40px;"&gt;&lt;/td&gt;
     &lt;td style="background-color: #cccccc; padding: 2px;"&gt;&lt;div style="font-size: 10pt;"&gt;
&lt;b&gt;Oracle TEXT für alle Daten: User Datastore&lt;/b&gt; 
     &lt;/div&gt;
&lt;div style="margin-top: 3px;"&gt;
Wie erzeugt man einen Oracle TEXT-Index auf mehrere Tabellen ...?
      &lt;/div&gt;
&lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;tr&gt;
     &lt;td colspan="2" rowspan="1" style="font-family: Helvetica,Arial,sans-serif;"&gt;17:00: Ende der Veranstaltung
     &lt;/td&gt;
     &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/tbody&gt; 
 &lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;
Es lohnt sich also - die Teilnahme an der Veranstaltung ist kostenlos, also am besten gleich anmelden. 
Termine und Anmeldeinformationen findet Ihr auf der &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/apex/veranstaltungen/201205-oracle-text/index.html" target="_blank"&gt;Workshop-Webseite&lt;/a&gt;.
&lt;/p&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-7671008878807819467?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/pClvyVAPRN0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/pClvyVAPRN0/workshop-zum-thema-oracle-text-mai-2012.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/04/workshop-zum-thema-oracle-text-mai-2012.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-8078053618376352589</guid><pubDate>Fri, 13 Apr 2012 09:26:00 +0000</pubDate><atom:updated>2012-04-13T10:26:26.826+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">plsql</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Thread</category><category domain="http://www.blogger.com/atom/ns#">sleep</category><category domain="http://www.blogger.com/atom/ns#">apex_util</category><category domain="http://www.blogger.com/atom/ns#">dbms_lock</category><title>SLEEP für eine Datenbanksession - ohne DBMS_LOCK</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;Let your DB session sleep without DBMS_LOCK!&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;p&gt;
 Recht häufig braucht man auch in der SQL- und PL/SQL Programmierung eine "SLEEP"-Funktion, also
 eine Funktion, die einfach nur eine bestimmte Anzahl Sekunden wartet und gar nichts tut. In der 
 Datenbank ist eine solche auch vorhanden. Im Package &lt;b&gt;DBMS_LOCK&lt;/b&gt; gibt es die Prozedur &lt;b&gt;SLEEP&lt;/b&gt; ...
&lt;/p&gt;
&lt;pre&gt;
SQL&amp;gt; desc dbms_lock
:
PROCEDURE SLEEP
 Argument Name                  Typ                     In/Out Defaultwert?
 ------------------------------ ----------------------- ------ --------
 SECONDS                        NUMBER                  IN
&lt;/pre&gt;
&lt;p&gt;
 So weit - so gut. Für den DBA.
&lt;/p&gt;
&lt;p&gt;
 Für den Entwickler ist es nicht so einfach - denn &lt;b&gt;DBMS_LOCK&lt;/b&gt; gehört nun nicht zu den 
 Paketen, auf die man normalerweise Zugriff hat. Ein GRANT von &lt;b&gt;DBMS_LOCK&lt;/b&gt; an &lt;b&gt;PUBLIC&lt;/b&gt; wird
 allerdings kaum ein DBA machen - aus guten Gründen, 
denn die anderen Funktionen in &lt;b&gt;DBMS_LOCK&lt;/b&gt; 
 sollten schon mit Vorsicht eingesetzt werden. 
&lt;/p&gt;
&lt;p&gt;
 Es gibt aber Alternativen. Wenn APEX in der Datenbank installiert ist, steht im Paket &lt;b&gt;APEX_UTIL&lt;/b&gt; 
 (welches jeder APEX Entwickler kennt), die Prozedur &lt;b&gt;PAUSE&lt;/b&gt; zur Verfügung. Diese arbeitet genauso
 wie &lt;b&gt;DBMS_LOCK.SLEEP&lt;/b&gt;, mit einer Ausnahme: Sie wartet maximal 2 Minuten (120 Sekunden), wie man 
 an der &lt;i&gt;nicht&lt;/i&gt; gewrappten Package Spec sehen kann.
&lt;/p&gt;
&lt;pre&gt;
procedure pause (
    --
    -- Pause for number of seconds identified by p_seconds
    --  (capped at 120 seconds)
    --
    p_seconds   in number)
    ;
&lt;/pre&gt;
&lt;p&gt;
 Da &lt;b&gt;APEX_UTIL&lt;/b&gt; an 
 PUBLIC gegranted ist, kann auch jeder andere Datenbankuser &lt;b&gt;APEX_UTIL.PAUSE&lt;/b&gt; nutzen.
 Datenbanken, in denen APEX nicht installiert ist, haben kein APEX_UTIL. Allerdings könnte
 man sich (als DBA) APEX zum Vorbild nehmen und eine allgemein nutzbare SLEEP-Funktion 
 bereitstellen. Da man die Datenbankprozesse unter Kontrolle behalten möchte, ist eine
 maximale Wartezeit (wie APEX es macht) eine gute Idee.
 Die eigene SLEEP-Funktion könnte also so aussehen:
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;replace&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/font&gt; global_sleep(p_seconds &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/font&gt;) &lt;font color="#804040"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/font&gt;
&lt;font color="#804040"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/font&gt;
  &lt;font color="#804040"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt; p_seconds &lt;font color="#804040"&gt;&lt;b&gt;&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;300&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; p_seconds &lt;font color="#804040"&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;0&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/font&gt; 
    &lt;font color="#008080"&gt;raise_application_error&lt;/font&gt;(&lt;font color="#804040"&gt;&lt;b&gt;-&lt;/b&gt;&lt;/font&gt;&lt;font color="#ff00ff"&gt;20000&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'SLEEP IS ONLY ALLOWED BETWEEN 1 SECOND AND 5 MINUTES'&lt;/font&gt;);
  &lt;font color="#804040"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/font&gt; 
    dbms_lock.sleep(p_seconds);
  &lt;font color="#804040"&gt;&lt;b&gt;end if&lt;/b&gt;&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/font&gt; global_sleep;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

&lt;font color="#008080"&gt;grant&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;execute&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;on&lt;/font&gt; global_sleep &lt;font color="#008080"&gt;to&lt;/font&gt; &lt;font color="#008080"&gt;public&lt;/font&gt;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#008080"&gt;public&lt;/font&gt; &lt;font color="#008080"&gt;synonym&lt;/font&gt; global_sleep &lt;font color="#804040"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/font&gt; sys.global_sleep
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 Das Ergebnis ist eine SLEEP-Funktion, die jeder nutzen kann, ohne dass das Paket &lt;b&gt;DBMS_LOCK&lt;/b&gt; freigegeben wird.
 Das Maximum liegt im Beispiel bei 5 Minuten - aber das kann ja jeder DBA so einstellen, wie er möchte. 
 Ich würde diesen Ansatz &lt;b&gt;sehr empfehlen&lt;/b&gt; - denn so bleiben die SLEEPs in einer kontrollierten
 Umgebung, mit mit &lt;b&gt;DBA_DEPENDENCIES&lt;/b&gt; kann der DBA auch jederzeit nachprüfen, wo das genutzt wird. 
&lt;/p&gt;
&lt;p&gt;
 Das ist aber noch nicht alles: Dem Entwickler bleibt, wenn der Zugriff auf &lt;b&gt;DBMS_LOCK&lt;/b&gt; fehlt, APEX
 nicht installiert ist und der DBA keine &lt;b&gt;GLOBAL_SLEEP&lt;/b&gt; Funktion bereitgestellt hat, noch eine dritte
 Möglichkeit: Nämlich mit Hilfe von Java in der Datenbank. 
&lt;/p&gt;
&lt;p&gt;
 Java kennt die Methode &lt;b&gt;sleep()&lt;/b&gt; in der Klasse &lt;b&gt;java.lang.Thread&lt;/b&gt;. Da Java in der Datenbank
 niemals multithreaded abläuft, sondern &lt;i&gt;alle&lt;/i&gt; Threads stets serialisiert werden, wirkt ein 
 &lt;b&gt;java.lang.Thread.sleep()&lt;/b&gt; genauso wie &lt;b&gt;DBMS_LOCK.SLEEP()&lt;/b&gt;. Und die Nutzung ist sehr einfach - außer einem &lt;b&gt;CREATE PROCEDURE&lt;/b&gt; sind keine besonderen
 Privilegien nötig.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;replace&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/font&gt; my_java_sleep (
  p_milli_seconds &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/font&gt;
) &lt;font color="#804040"&gt;&lt;b&gt;as&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;language&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;java&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'java.lang.Thread.sleep(long)'&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

SQL&amp;gt; exec my_java_sleep(5000);

PL/SQL-Prozedur erfolgreich abgeschlossen.

Abgelaufen: 00:00:05.00
SQL&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
 Wie man sieht: Es gibt einige Möglichkeiten für eine SLEEP-Funktion - Zugriff auf das
 mächtige &lt;b&gt;DBMS_LOCK&lt;/b&gt; ist dafür (im Gegensatz zur landläufigen Meinung) gar nicht nötig.
&lt;/p&gt;
&lt;/div&gt;










&lt;div lang="en" style="display: none;"&gt;
&lt;p&gt;
 Sometimes a developer needs a "sleep" function - this is not only true in Java or C/C++, but also
 in SQL and PL/SQL programming environments. Looking into the Oracle documentation one will quickly
 find the procedure &lt;b&gt;SLEEP&lt;/b&gt; in the &lt;b&gt;DBMS_LOCK&lt;/b&gt; package.
&lt;/p&gt;
&lt;pre&gt;
SQL&amp;gt; desc dbms_lock
:
PROCEDURE SLEEP
 Argument Name                  Typ                     In/Out Defaultwert?
 ------------------------------ ----------------------- ------ --------
 SECONDS                        NUMBER                  IN
&lt;/pre&gt;
&lt;p&gt;
 So far - so good. If you have DBA privileges.
&lt;/p&gt;
&lt;p&gt;
 But most developers do not have these. And &lt;b&gt;DBMS_LOCK&lt;/b&gt; is a package which should not 
 be granted to everyone - it's far too mighty. So a developer would at least have
 a discussion with his DBA before getting access to &lt;b&gt;DBMS_LOCK&lt;/b&gt;. But there are some
 alternatives ...
&lt;/p&gt;
&lt;p&gt;
 When APEX has been installed into the database there is the package &lt;b&gt;APEX_UTIL&lt;/b&gt;. 
 It 
 contains a procedure &lt;b&gt;PAUSE&lt;/b&gt; which does exactly the same as &lt;b&gt;DBMS_LOCK.SLEEP&lt;/b&gt; with
 one exception: The sleeping time is being capped at &lt;b&gt;120&lt;/b&gt; seconds, which we can see by 
 examining the package spec of &lt;b&gt;APEX_UTIL&lt;/b&gt;.
&lt;/p&gt;
&lt;pre&gt;
procedure pause (
    --
    -- Pause for number of seconds identified by p_seconds
    --  (capped at 120 seconds)
    --
    p_seconds   in number)
    ;
&lt;/pre&gt;
&lt;p&gt;
 Since &lt;b&gt;APEX_UTIL&lt;/b&gt; is a public package it can be used
 without the need for special privileges. If APEX is &lt;i&gt;not&lt;/i&gt; present in the database I'd recommend
 to take this appraoch as a template: The DBA could build an own public SLEEP funktion and
 make this available to all developers. Here is an example implemention:
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;replace&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/font&gt; global_sleep(p_seconds &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/font&gt;) &lt;font color="#804040"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/font&gt;
&lt;font color="#804040"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/font&gt;
  &lt;font color="#804040"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt; p_seconds &lt;font color="#804040"&gt;&lt;b&gt;&amp;gt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;300&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; p_seconds &lt;font color="#804040"&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;0&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/font&gt; 
    &lt;font color="#008080"&gt;raise_application_error&lt;/font&gt;(&lt;font color="#804040"&gt;&lt;b&gt;-&lt;/b&gt;&lt;/font&gt;&lt;font color="#ff00ff"&gt;20000&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'SLEEP IS ONLY ALLOWED BETWEEN 1 SECOND AND 5 MINUTES'&lt;/font&gt;);
  &lt;font color="#804040"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/font&gt; 
    dbms_lock.sleep(p_seconds);
  &lt;font color="#804040"&gt;&lt;b&gt;end if&lt;/b&gt;&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/font&gt; global_sleep;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

&lt;font color="#008080"&gt;grant&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;execute&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;on&lt;/font&gt; global_sleep &lt;font color="#008080"&gt;to&lt;/font&gt; &lt;font color="#008080"&gt;public&lt;/font&gt;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#008080"&gt;public&lt;/font&gt; &lt;font color="#008080"&gt;synonym&lt;/font&gt; global_sleep &lt;font color="#804040"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/font&gt; sys.global_sleep
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 As a result, we have a special sleep function which is available to everyone in the
 database. Of course, it would also be possible to grant execution privilege to a special
 developer role instead of &lt;b&gt;PUBLIC&lt;/b&gt;. The limits (here: 5 minutes) and the violation rule (APEX: quiet capping, here: raise an exception) can
 be implemented according to individual needs.
 Personally I'd strongly recommend an approach like this: The DBA keeps control, since it is his own
 procedure. He can control its behaviour and he can (via &lt;b&gt;DBA_DEPENDENCIES&lt;/b&gt;) always see where is is being used.  
&lt;/p&gt;
&lt;p&gt;
 But that's not all - we have another alternative: Imagine, we have &lt;i&gt;no&lt;/i&gt; access to DBMS_LOCK, there is &lt;i&gt;no&lt;/i&gt; "global" SLEEP
 funktion as described above, APEX is &lt;i&gt;not&lt;/i&gt; installed and we &lt;i&gt;need&lt;/i&gt; a sleep funcktion. 
 The solution: Use &lt;b&gt;Java in the Database&lt;/b&gt;.
&lt;/p&gt;
&lt;p&gt;
 Java has the method &lt;b&gt;sleep()&lt;/b&gt; within the class &lt;b&gt;java.lang.Thread&lt;/b&gt;. Java in the database
 supports the complete multithreading API (there is no "real" multithreading, since all threads are 
 being serialized). 
 Therefore we can use &lt;b&gt;java.lang.Thread.sleep()&lt;/b&gt; to let the database
 session sleep for the given amount of milliseconds. Summarized: &lt;b&gt;Thread.sleep()&lt;/b&gt; does the same
 as &lt;b&gt;DBMS_LOCK.SLEEP&lt;/b&gt;. But opposed to that, no special privileges are needed and
 every database user with the &lt;b&gt;CREATE PROCEDURE&lt;/b&gt; privilege can use it.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#008080"&gt;create&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#008080"&gt;replace&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/font&gt; my_java_sleep (
  p_milli_seconds &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/font&gt;
) &lt;font color="#804040"&gt;&lt;b&gt;as&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;language&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;java&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'java.lang.Thread.sleep(long)'&lt;/font&gt;;
&lt;font color="#804040"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;

SQL&amp;gt; exec my_java_sleep(5000);

PL/SQL procedure successfully completed.

Abgelaufen: 00:00:05.00
SQL&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
 So - you don't really need special privileges in order to let your database session sleep for 
 a while. But having one global procedure (similar to APEX) is most probably the best approach.
&lt;/p&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-8078053618376352589?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/b4ghBocvNEc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/b4ghBocvNEc/sleep-fur-eine-datenbanksession-ohne.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/04/sleep-fur-eine-datenbanksession-ohne.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-5088605714230282392</guid><pubDate>Thu, 29 Mar 2012 07:06:00 +0000</pubDate><atom:updated>2012-03-29T11:00:03.898+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">event</category><category domain="http://www.blogger.com/atom/ns#">veranstaltung</category><category domain="http://www.blogger.com/atom/ns#">muniqsoft</category><category domain="http://www.blogger.com/atom/ns#">düsseldorf</category><category domain="http://www.blogger.com/atom/ns#">apex</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">berlin</category><category domain="http://www.blogger.com/atom/ns#">münchen</category><category domain="http://www.blogger.com/atom/ns#">mtag</category><title>APEX Entwicklertag: Ende April in München, Düsseldorf und Berlin</title><description>&lt;div lang="de"&gt;
&lt;div&gt;&lt;b&gt;Sehen wir uns dort ...?&lt;/b&gt;&lt;/div&gt;
&lt;hr/&gt;
&lt;i&gt;
&lt;div&gt;In 2004 wurde Application Express (APEX) zusammen mit Oracle10&lt;i&gt;g&lt;/i&gt; herausgebracht. Acht Jahre später
   kann sich die Zwischenbilanz sehen lassen: Allein &lt;b&gt;in der deutschsprachigen Community&lt;/b&gt; sind
   1200 Leser registriert - in Unternehmen mit Oracle-Infrastruktur entstehen neue APEX-Anwendungen 
   teilweise täglich.
   Und APEX-Entwickler machen weit mehr als Masken zur Datenerfassung: Sie beschäftigen sich 
   mit Themen wie APEX-Anwendungen fürmobile Endgeräte , Entwicklung moderner "Web 2.0"-Oberflächen, Cloud Computing und mehr. 
&lt;/div&gt;
&lt;div&gt;
   Wichtig ist
   aber immer das persönliche Kennenlernen, der Austausch und die Diskussion. Aus diesem Grund
   trifft sich die deutschsprachige APEX Community im&lt;b&gt; April 2012&lt;/b&gt; in &lt;b&gt;München&lt;/b&gt;, &lt;b&gt;Düsseldorf &lt;/b&gt;und &lt;b&gt;Berlin&lt;/b&gt;.
 Auf diesem Entwicklertag erhalten Sie einen Einblick in aktuelle 
Entwicklerthemen rund um Application Express: Wir informieren über den 
aktuellen Stand in APEX 4.1 und werden speziell das Thema "mobile 
APEX-Anwendungen" beleuchten. Unser Partnern Muniqsoft informiert über 
Layoutvarianten in APEX-Anwendungen - mit Tipps &amp;amp; Tricks direkt aus 
der Praxis. Die MT AG schließlich wird Implementierungsvarianten für 
gängige Aufgabenstellungen vorstellen - wiederum mit ganz konkretem 
Bezug zu praktischen Projekten.
&lt;/div&gt;
&lt;div&gt;
Lassen
 Sie sich diese Möglichkeit zum direkten Erfahrungsaustausch nicht 
entgehen. Genaue Zeiten, Orte, die detaillierte Agenda und 
Anmeldeinformationen finden Sie auf der &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/apex/veranstaltungen/201204-community/index.html" target="_blank" title="Veranstaltungsdetails"&gt;Veranstaltungs-Webseite&lt;/a&gt;. &lt;b&gt;Die Teilnahme an der Veranstaltung ist kostenlos&lt;/b&gt;. &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/apex/veranstaltungen/201204-community/index.html" target="_blank" title="Anmeldung"&gt;Melden Sie sich noch heute an&lt;/a&gt;.
&lt;/div&gt;
&lt;/i&gt;
&lt;hr/&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;This blog posting is about a german-language event in Munich, Dusseldorf and Berlin and therefore in german only.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-5088605714230282392?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/G0cY2Zr653M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/G0cY2Zr653M/apex-entwicklertag-ende-april-in.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/03/apex-entwicklertag-ende-april-in.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-4939852777218574569</guid><pubDate>Mon, 12 Mar 2012 07:40:00 +0000</pubDate><atom:updated>2012-03-13T11:36:19.069+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">data</category><category domain="http://www.blogger.com/atom/ns#">plsql</category><category domain="http://www.blogger.com/atom/ns#">ftp</category><category domain="http://www.blogger.com/atom/ns#">dump</category><category domain="http://www.blogger.com/atom/ns#">directory</category><category domain="http://www.blogger.com/atom/ns#">scp</category><category domain="http://www.blogger.com/atom/ns#">asm</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">dbms_file_transfer</category><title>Filetransfer mit FTP oder SCP? Nein, mit der Oracle-Datenbank!</title><description>&lt;div lang="en" style="color: #cc6600; display: none;"&gt;
Transfer files with FTP or SCP? - No! Use the Oracle DB!&lt;/div&gt;
&lt;div lang="de"&gt;
Wusstet Ihr schon, dass Ihr Dateien von eine, Oracle-Datenbankserver auf einen anderen
 ohne Betriebssystem-Login übertragen könnt ...? Ihr braucht weder SCP, nocht FTP oder andere
 Dateitransferprogramme - nur die Oracle-Datenbank auf beiden Maschinen. Und solche Situationen
 sind ja durchaus normal ...
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Man macht einen Data Pump-Export auf der Quelldatenbank. Die Dump-Datei liegt nun im Dateisystem
    des Datenbankservers. &lt;/li&gt;
&lt;li&gt;Diese Datei muss auf den anderen Datenbankserver übertragen werden. Normalerweise nutzt man hierfür
    dann FTP. SCP oder ähnliche Werkzeuge&lt;/li&gt;
&lt;li&gt;Auf dem Zielsystem wird der Dump dann per Import wieder eingespielt.&lt;/li&gt;
&lt;/ul&gt;
Wenn man nun keinen Betriebssystem-Login hat (oder der System-Admin gerade nicht da ist), geht es
 in der Tat auch ohne: Mit dem PL/SQL Paket &lt;b&gt;DBMS_FILE_TRANSFER&lt;/b&gt;. Ihr braucht dazu:
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Ein Directory-Objekt auf dem Quellsystem - die zu kopierende Datei sollte in diesem Verzeichnis sein:&lt;br /&gt;
&lt;pre&gt;create directory srcdir as '/path/to/src/folder/';

grant read on directory srcdir to send_user;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Ein Directory-Objekt auf dem Zielsystem:&lt;br /&gt;
&lt;pre&gt;create directory dstdir as '/path/to/dest/folder/';

grant write on directory destdir to receive_user;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Einen Database Link vom Quellsystem zum Zielsystem:&lt;br /&gt;
&lt;pre&gt;create database link dblink_dest_system connect to receive_user identified by {password}
using 'destDatabase'
&lt;/pre&gt;
Übrigens muss die Ziel-Datenbank nicht zwingend in der tnsnames.ora hinterlegt sein. Im Notfall
tut es auch ein Easy-Connect wie folgt: &lt;b&gt;&lt;code&gt;using 'destDatabase:1521/service.domain.com'&lt;/code&gt;&lt;/b&gt;
&lt;/li&gt;
&lt;/ul&gt;
Ist das alles getan, so kann der Dateitransfer angestoßen werden: Data Pump Exports sind sicherlich
 sehr naheliegend - &lt;b&gt;DBMS_FILE_TRANSFER&lt;/b&gt; überträgt aber auch andere Dateitypen (deren Dateigröße muss aber
 ein Vielfaches von 512 sein).
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
  dbms_file_transfer.put_file(
    source_directory_object      &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'SRCDIR'&lt;/span&gt;,
    source_file_name             &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'file-to-transfer'&lt;/span&gt;,
    destination_directory_object &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'DSTDIR'&lt;/span&gt;,
    destination_file_name        &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'new-filename-on-dest-system'&lt;/span&gt;,
    destination_database         &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'dblink_dest_system'&lt;/span&gt;
  );
&lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/pre&gt;
Und Voilá. Ein Blick in das Verzeichnis auf dem Zielsystem sollte zeigen, dass die Datei angekommen ist. Besonders  interessant ist das übrigens beim Einsatz der ASM-Technologie - denn wenn Dateien aus dem ASM gelesen oder in dieses geschrieben werden sollen, geht das nicht ohne weiteres mit Betriebssystem-Mitteln. Der Weg über &lt;b&gt;DBMS_FILE_TRANSFER&lt;/b&gt; ist in solchen Fällen sogar der einfachere ... 
&lt;br /&gt;
Mehr Information zu DBMS_FILE_TRANSFER findet Ihr in der &lt;a href="http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_ftran.htm#i999064" target="_blank"&gt;Dokumentation&lt;/a&gt; oder in einem Tipp von den Kollegen der &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/DB_filecopy/index.html" target="_blank"&gt;DBA Community&lt;/a&gt;.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Did you know that you can transfer normal operating system files from one database server to 
 another ... wothout logging into the operating system? You need neither SCP, nor FTP or any
 other file transfer program - just the Oracle database on both systems - and this is a quite
 common situation ...
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;One does a datapump export on the source database. The resulting dumpfile is now within a directory
    on the database server's filesystem.&lt;/li&gt;
&lt;li&gt;This file needs to be moved to the target system. Most often operating system methods are employed for this task.&lt;/li&gt;
&lt;li&gt;On the target system the dumpfile is being imported into the database.&lt;/li&gt;
&lt;/ul&gt;
So far - so good. But when logging into the operating system is not possible (either we don't have
 an account and the Sysadmin is not here or our account is locked or ... or ...) we can't transfer 
 the file. But we don't need to - we just need &lt;b&gt;DBMS_FILE_TRANSFER&lt;/b&gt; and a bit of preparation ...
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Create a directory object on the source database - the file to be transferred should reside in that directory:&lt;br /&gt;
&lt;pre&gt;create directory srcdir as '/path/to/src/folder/';

grant read on directory srcdir to send_user;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Then create a directory object on the target database. The file will be placed into that folder:&lt;br /&gt;
&lt;pre&gt;create directory dstdir as '/path/to/dest/folder/';

grant write on directory destdir to receive_user;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;And finally we need a database link from the source to the target system:&lt;br /&gt;
&lt;pre&gt;create database link dblink_dest_system connect to receive_user identified by {password}
using 'destDatabase'
&lt;/pre&gt;
BTW: The target database does not need to be contained in &lt;b&gt;tnsnames.ora&lt;/b&gt;. Easy Connect Syntax is also possible as
follows: &lt;b&gt;&lt;code&gt;using 'destDatabase:1521/service.domain.com'&lt;/code&gt;&lt;/b&gt;. We just don't need to log into the operating system.
&lt;/li&gt;
&lt;/ul&gt;
When all preparations are done the file transfer operation can be started - and it is so simple. Datapump Dumpfiles are
 a quite common scenario - but &lt;b&gt;DBMS_FILE_TRANSFER&lt;/b&gt; works with all kind of files (but keep in mind that the filesize must be
 a multiple of 512).
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
  dbms_file_transfer.put_file(
    source_directory_object      &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'SRCDIR'&lt;/span&gt;,
    source_file_name             &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'file-to-transfer'&lt;/span&gt;,
    destination_directory_object &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'DSTDIR'&lt;/span&gt;,
    destination_file_name        &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'new-filename-on-dest-system'&lt;/span&gt;,
    destination_database         &lt;span style="color: #804040;"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'dblink_dest_system'&lt;/span&gt;
  );
&lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/pre&gt;
There is also the procedure &lt;b&gt;GET_FILE&lt;/b&gt; - which does the operation vice-versa.  
&lt;br /&gt;
Done. Looking into the directory on the target system should show that the file is now present. This technique is particular interesting
 when it's about reading from or writing to Oracle's ASM - if the source or target database uses ASM (which cannot be easily accessed with 
 normal operating system commands) this approach is the most simple one. 
&lt;br /&gt;
More information about  &lt;b&gt;DBMS_FILE_TRANSFER&lt;/b&gt; is contained in the &lt;a href="http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_ftran.htm#i999064" target="_blank"&gt;documentation&lt;/a&gt;.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-4939852777218574569?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/2tmN2eQvulI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/2tmN2eQvulI/filetransfert-mit-ftp-oder-scp-nein-mit.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>2</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/03/filetransfert-mit-ftp-oder-scp-nein-mit.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-3142184473540646297</guid><pubDate>Mon, 05 Mar 2012 08:21:00 +0000</pubDate><atom:updated>2012-03-05T09:21:07.449+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">stammtisch</category><category domain="http://www.blogger.com/atom/ns#">apex</category><title>APEX und PL/SQL Entwicklerstammtisch in München</title><description>&lt;p lang="de"&gt;
 Die APEX und PL/SQL Entwicklercommunity trifft sich zum lockeren "&lt;b&gt;APEX Stammtisch&lt;/b&gt;" am 
13.03.2012 um 19:30 Uhr in München. Einfach nur ein leckeres Bier, gutes 
Essen, interessante Gespräche rund um APEX und interessante Leute. Ein Tisch ist im "Augustiner Restaurant" in München reserviert.&lt;br /&gt;
&lt;br /&gt;


 Neuhauserstr. 27&lt;br /&gt;
 &lt;strong&gt;80331 München&lt;/strong&gt;&lt;br /&gt;

&lt;br /&gt;
http://augustiner-restaurant.com/&lt;br /&gt;

&lt;br /&gt;
Bitte meldet euch hier kurz an, damit wir wissen, wie viele kommen und ob und wann wir einen größeren Tisch reservieren müssen.&lt;br /&gt;
https://apex.oracle.com/pls/apex/f?p=18226:1:::::P1_EVENT_ID:361 
&lt;/p&gt;
&lt;p lang="en" style="display: none"&gt;
This posting is about the "APEX Stammtisch" event in Munich and therefore in German only.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-3142184473540646297?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/5uCeQ08pZ9U" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/5uCeQ08pZ9U/apex-und-plsql-entwicklerstammtisch-in.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/03/apex-und-plsql-entwicklerstammtisch-in.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-2190141705167884235</guid><pubDate>Fri, 24 Feb 2012 09:14:00 +0000</pubDate><atom:updated>2012-02-24T10:14:35.906+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">having</category><category domain="http://www.blogger.com/atom/ns#">group</category><title>SQL HAVING ... Kennt jeder, oder?</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;Everyone knows SQL HAVING ...?&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;p&gt;
 Dieses Blog Posting widme SQL &lt;b&gt;HAVING&lt;/b&gt;. Das sieht dann zwar eher nach "SQL Grundkurs" aus, aber
 mir fällt schon auf, dass &lt;b&gt;HAVING&lt;/b&gt; in der Praxis gerne vergessen und durch Subselects "emuliert" wird.
 Und das muss ja nicht sein. Also machen wir heute ein kurzes, aber einfaches Blog Posting zum Thema
 &lt;b&gt;HAVING&lt;/b&gt;. Wie immer, reicht die Tabelle &lt;b&gt;EMP&lt;/b&gt; als Beispiel völlig aus.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; 
  d.dname, 
  sum(e.sal) sal_sum,
  count(e.empno) emp_cnt
&lt;font color="#6a5acd"&gt;from&lt;/font&gt; emp e join dept d &lt;font color="#6a5acd"&gt;on&lt;/font&gt; (d.deptno = e.deptno)
&lt;font color="#6a5acd"&gt;group&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; d.dname

DNAME             SAL_SUM    EMP_CNT
-------------- ---------- ----------
ACCOUNTING           8750          3
RESEARCH            10875          5
SALES                9400          6
&lt;/pre&gt;
&lt;p&gt;
 Nun möchten wir nur die Abteilungen mit mindestens 5 Mitarbeitern haben ... häufig findet man dann
 diese Lösung, die auch durchaus funktioniert ... 
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; * &lt;font color="#6a5acd"&gt;from&lt;/font&gt; (
  &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; 
    d.dname, 
    sum(e.sal) sal_sum,
    count(e.empno) emp_cnt
  &lt;font color="#6a5acd"&gt;from&lt;/font&gt; emp e join dept d &lt;font color="#6a5acd"&gt;on&lt;/font&gt; (d.deptno = e.deptno)
  &lt;font color="#6a5acd"&gt;group&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; d.dname
) 
&lt;font color="#6a5acd"&gt;where&lt;/font&gt; emp_cnt &amp;gt;= &lt;font color="#ff00ff"&gt;5&lt;/font&gt;

DNAME             SAL_SUM    EMP_CNT
-------------- ---------- ----------
RESEARCH            10875          5
SALES                9400          6
&lt;/pre&gt;
&lt;p&gt;
 Analog geht es natürlich auch mit der WITH-Klausel. Es geht aber auch eleganter, denn für das
 Filtern auf aggregierten Werten gibt es eben &lt;b&gt;HAVING&lt;/b&gt;.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; 
  d.dname, 
  sum(e.sal) sal_sum,
  count(e.empno) emp_cnt
&lt;font color="#6a5acd"&gt;from&lt;/font&gt; emp e join dept d &lt;font color="#6a5acd"&gt;on&lt;/font&gt; (d.deptno = e.deptno)
&lt;font color="#6a5acd"&gt;group&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; d.dname
&lt;font color="#6a5acd"&gt;having&lt;/font&gt; count(e.empno) &amp;gt; &lt;font color="#ff00ff"&gt;5&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 So ... und das war's auch schon für heute ...
&lt;/p&gt;
&lt;/div&gt;










&lt;div lang="en" style="display: none;"&gt;
&lt;p&gt;
 Today I'll post about SQL &lt;b&gt;HAVING&lt;/b&gt;. This looks a bit like "SQL - Lesson 1", but my observation is
 that HAVING is very often "emulated" with subqueries or &lt;b&gt;WITH&lt;/b&gt; clauses. Using the &lt;b&gt;HAVING&lt;/b&gt; clause would make
 some SQL queries simpler - and for that reason: This short posting is about SQL &lt;b&gt;HAVING&lt;/b&gt; . As always,
 I'll use the well-known table &lt;b&gt;EMP&lt;/b&gt; as example.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; 
  d.dname, 
  sum(e.sal) sal_sum,
  count(e.empno) emp_cnt
&lt;font color="#6a5acd"&gt;from&lt;/font&gt; emp e join dept d &lt;font color="#6a5acd"&gt;on&lt;/font&gt; (d.deptno = e.deptno)
&lt;font color="#6a5acd"&gt;group&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; d.dname

DNAME             SAL_SUM    EMP_CNT
-------------- ---------- ----------
ACCOUNTING           8750          3
RESEARCH            10875          5
SALES                9400          6
&lt;/pre&gt;
&lt;p&gt;
 Now we want to have only the departments with more than 5 employees. The following
 query is quite often being used in  such scenarios. And it works fine ...
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; * &lt;font color="#6a5acd"&gt;from&lt;/font&gt; (
  &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; 
    d.dname, 
    sum(e.sal) sal_sum,
    count(e.empno) emp_cnt
  &lt;font color="#6a5acd"&gt;from&lt;/font&gt; emp e join dept d &lt;font color="#6a5acd"&gt;on&lt;/font&gt; (d.deptno = e.deptno)
  &lt;font color="#6a5acd"&gt;group&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; d.dname
) 
&lt;font color="#6a5acd"&gt;where&lt;/font&gt; emp_cnt &amp;gt;= &lt;font color="#ff00ff"&gt;5&lt;/font&gt;

DNAME             SAL_SUM    EMP_CNT
-------------- ---------- ----------
RESEARCH            10875          5
SALES                9400          6
&lt;/pre&gt;
&lt;p&gt;
 A SQL WITH clause would also work, of course. But the more elegant solution to filter 
 on aggregated values is &lt;b&gt;HAVING&lt;/b&gt;.
&lt;/p&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; 
  d.dname, 
  sum(e.sal) sal_sum,
  count(e.empno) emp_cnt
&lt;font color="#6a5acd"&gt;from&lt;/font&gt; emp e join dept d &lt;font color="#6a5acd"&gt;on&lt;/font&gt; (d.deptno = e.deptno)
&lt;font color="#6a5acd"&gt;group&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; d.dname
&lt;font color="#6a5acd"&gt;having&lt;/font&gt; count(e.empno) &amp;gt; &lt;font color="#ff00ff"&gt;5&lt;/font&gt;
&lt;/pre&gt;
&lt;p&gt;
 And that's it ... 
&lt;/p&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-2190141705167884235?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/OgLHJ0zw1Yc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/OgLHJ0zw1Yc/sql-having-kennt-jeder-oder.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/02/sql-having-kennt-jeder-oder.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-8095290745361161262</guid><pubDate>Fri, 10 Feb 2012 07:56:00 +0000</pubDate><atom:updated>2012-02-10T09:01:01.368+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">vortrag</category><category domain="http://www.blogger.com/atom/ns#">entwickler</category><category domain="http://www.blogger.com/atom/ns#">konferenz</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>DOAG Entwicklerkonferenz im Juni 2012!</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;DOAG Developer conference&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;p&gt;
 Heute ist es mal nichts technisches: Ich möchte einfach nur auf eine DOAG-Veranstaltung hinweisen, die ich sehr interessant finde.
 Ich zitiere aus dem Call for Papers der DOAG:
&lt;/p&gt;
&lt;div style="border: 1px solid black; padding: 3px;"&gt;
&lt;i&gt;
Erstmals veranstaltet die DOAG in Bonn eine &lt;b&gt;Konferenz für den Erfahrungsaustausch der Software-Entwickler&lt;/b&gt;, die DOAG 2012 Development. Am &lt;b&gt;14. Juni 2012&lt;/b&gt; verwandelt sich das Maritim Hotel Bonn zum Brennpunkt der Development-Szene im Oracle-Umfeld. Seien Sie dabei und tauchen Sie tief in die Software-Entwicklung mittels Tools und Technologien aus dem Hause Oracle ein! Im Mittelpunkt stehen der Erfahrungsaustausch zu Java, JDeveloper und PL/SQL, aber auch zu den Werkzeugen SQL Forms und Reports.
&lt;p&gt;
&lt;br/&gt;
 – C A L L&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;F O R&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbspP R E S E N T A T I O N S –
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;
Werden Sie Referent auf der DOAG 2012 Development! Reichen Sie ab sofort Ihr Vortragsangebot &lt;a href="https://www.doag.org/termine/cfp.php?id=437614" target="_blank"&gt;hier online&lt;/a&gt; ein!
&lt;/p&gt;
&lt;p&gt;
Sie haben bis zum 05. März 2012 die Gelegenheit, sich um einen Vortrag zu bewerben! Als Referent erhalten Sie natürlich freien Eintritt zur Konferenz. Wir suchen Vorträge zu folgenden Themenbereichen:
&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;SQL und DB-Design&lt;/li&gt;&lt;li&gt;PL/SQL und Apex&lt;/li&gt;&lt;li&gt;Forms und ADF&lt;/li&gt;&lt;li&gt;Reporting und BI&lt;/li&gt;&lt;li&gt;Karten und Geodaten (Spatial)&lt;/li&gt;&lt;li&gt;SOA und BPM&lt;/li&gt;&lt;li&gt; Java und Open Source&lt;/li&gt;&lt;li&gt; Strategie und Software-Architektur&lt;/li&gt;&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Wir freuen uns auf Ihre Vortragsbewerbung!
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;
Alle weiteren Informationen zur DOAG 2012 Development erhalten Sie hier:&lt;br/&gt;
&lt;a href="http://www.doag.org/events/konferenzen/doag-2012-development.html" target="_blank"&gt;http://www.doag.org/events/konferenzen/doag-2012-development.html&lt;/a&gt;
&lt;/p&gt;
&lt;/i&gt;
&lt;/div&gt;
&lt;p&gt;
 Ich werde auf jeden Fall Vorträge einreichen - und hoffe, dass diese a) etwas angenommen werden und b) dass ich mich dort mit vielen anderen Entwicklern austauschen kann.
&lt;/p&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;This posting is about a german users' group conference and therefore in german only.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-8095290745361161262?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/y1xW4jG2UuI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/y1xW4jG2UuI/doag-developer-conference-heute-ist-es.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/02/doag-developer-conference-heute-ist-es.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-6139405337299966715</guid><pubDate>Mon, 30 Jan 2012 13:04:00 +0000</pubDate><atom:updated>2012-01-30T14:04:33.583+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">xdb</category><category domain="http://www.blogger.com/atom/ns#">xmlpatch</category><category domain="http://www.blogger.com/atom/ns#">xml</category><category domain="http://www.blogger.com/atom/ns#">xmldiff</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>XML Dokumente mit SQL vergleichen: XMLDIFF und XMLPATCH</title><description>&lt;div lang="en" style="color: #cc6600; display: none;"&gt;
Comparing XML with SQL: XMLDIFF and XMLPATCH&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;div&gt;
Heute möchte ich etwas über zwei  ganz interessante SQL-Funktionen in der Datenbank schreiben: &lt;b&gt;XMLDIFF&lt;/b&gt; 
 und &lt;b&gt;XMLPATCH&lt;/b&gt;. Fangen wir mit &lt;b&gt;XMLDIFF&lt;/b&gt; an: Es vergleicht XML-Dokumente. Und dazu am besten mal ein
 Beispiel ...
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;document&lt;/span&gt;&lt;span style="color: teal;"&gt; &lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;xmlns&lt;/b&gt;&lt;/span&gt;=&lt;span style="color: magenta;"&gt;"my-namespace"&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;leeres-xmltag&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;lt;/leeres-xmltag&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;xmltag-inhalt&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;"&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;/xmltag-inhalt&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: teal;"&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;

&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;document&lt;/span&gt;&lt;span style="color: teal;"&gt; &lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;xmlns&lt;/b&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;ns&lt;/b&gt;&lt;/span&gt;=&lt;span style="color: magenta;"&gt;"my-namespace"&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;leeres-xmltag&lt;/span&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;xmltag-inhalt&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;quot&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;/ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;xmltag-inhalt&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: teal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;document&amp;gt;&lt;/span&gt; 
&lt;/pre&gt;
&lt;div&gt;
Die Frage "Worin unterscheiden sich die beiden XML-Dokumente?" ist nur auf den ersten
Blick einfach. Probieren wir die &lt;b&gt;XMLDIFF&lt;/b&gt;-Funktion einfach mal aus ...
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; xmldiff(
 xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;document xmlns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;leeres-xmltag&amp;gt;&amp;lt;/leeres-xmltag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;xmltag-inhalt&amp;gt;"&amp;lt;/xmltag-inhalt&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/document&amp;gt;'&lt;/span&gt;
 ), xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;ns:document xmlns:ns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:leeres-xmltag/&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:xmltag-inhalt&amp;gt;&amp;amp;quot;&amp;lt;/ns:xmltag-inhalt&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/ns:document&amp;gt;'&lt;/span&gt;
 )
) &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; dual
/ 

XMLDIFF(XMLTYPE('&amp;lt;DOCUMENTXMLNS="MY-NAMESPACE"&amp;gt;&amp;lt;LEERES-XMLTAG&amp;gt;&amp;lt;/LEERES-XMLTAG&amp;gt;&amp;lt;X
--------------------------------------------------------------------------------
&amp;lt;xd:xdiff xsi:schemaLocation="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt; &lt;a href="http://xmlns/"&gt;http://xmlns&lt;/a&gt;
.oracle.com/xdb/xdiff.xsd" xmlns:xd="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt;" xmln
s:ns="my-namespace" xmlns:xsi="&lt;a href="http://www.w3.org/2001/XMLSchema-instance"&gt;http://www.w3.org/2001/XMLSchema-instance&lt;/a&gt;"&amp;gt;
  &amp;lt;?oracle-xmldiff operations-in-docorder="true" output-model="snapshot" diff-al
gorithm="global"?&amp;gt;
&amp;lt;/xd:xdiff&amp;gt;
&lt;/pre&gt;
&lt;div&gt;
Die XMLDIFF-Funktion liefert zwar etwas zurück, bei genauer Betrachtung stellt man jedoch
 fest, dass das Tag &lt;b&gt;xd:xdiff&lt;/b&gt; leer ist - es wurden also keine Unterschiede zwischen den XML-Dokumenten
 festgestellt - und das ist auch richtig so. Denn die im Text sichtbaren Unterschiede haben nach
 dem XML-Standard keine Bedeutung. Ein leeres Tag darf sowohl &lt;b&gt;&amp;lt;tag&amp;gt;&amp;lt;/tag&amp;gt;&lt;/b&gt; als auch
 &lt;b&gt;&amp;lt;tag/&amp;gt;&lt;/b&gt; geschrieben werden. Gleiches gilt für Zeichenentities oder Namensräume. XMLDIFF
 ist also zunächst eine sehr interessante Funktion, um überhaupt Unterschiede zwischen XML-Dokumenten
 zu erkennen. Doch &lt;b&gt;XMLDIFF&lt;/b&gt; leistet noch mehr: Nehmen wir mal zwei XML-Dokumente, die sich tatsächlich
 unterscheiden ...
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; xmldiff(
 xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;document xmlns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text 1&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text 3&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/document&amp;gt;'&lt;/span&gt;
 ), xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;ns:document xmlns:ns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:tag&amp;gt;Text 1&amp;lt;/ns:tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:tag&amp;gt;Text 2&amp;lt;/ns:tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:tag option="a"&amp;gt;Text 3&amp;lt;/ns:tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/ns:document&amp;gt;'&lt;/span&gt;
 )
) as xml_diff &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; dual
/ 

XML_DIFF
------------------------------------------------------------------------------------------
&amp;lt;xd:xdiff xsi:schemaLocation="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt; &lt;a href="http://xmlns.oracle.co/"&gt;http://xmlns.oracle.co&lt;/a&gt;
m/xdb/xdiff.xsd" xmlns:xd="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt;" xmlns:ns="my-namespace"
xmlns:xsi="&lt;a href="http://www.w3.org/2001/XMLSchema-instance"&gt;http://www.w3.org/2001/XMLSchema-instance&lt;/a&gt;"&amp;gt;
  &amp;lt;?oracle-xmldiff operations-in-docorder="true" output-model="snapshot" diff-algorithm="g
lobal"?&amp;gt;&lt;span style="color: red;"&gt;
  &amp;lt;xd:update-node xd:node-type="text" xd:xpath="/ns:document[1]/ns:tag[2]/text()[1]"&amp;gt;
    &amp;lt;xd:content&amp;gt;Text 2&amp;lt;/xd:content&amp;gt;
  &amp;lt;/xd:update-node&amp;gt;
  &amp;lt;xd:append-node xd:node-type="element" xd:parent-xpath="/ns:document[1]"&amp;gt;
    &amp;lt;xd:content&amp;gt;
      &amp;lt;ns:tag option="a"&amp;gt;Text 3&amp;lt;/ns:tag&amp;gt;
    &amp;lt;/xd:content&amp;gt;
  &amp;lt;/xd:append-node&amp;gt;&lt;/span&gt;
&amp;lt;/xd:xdiff&amp;gt;
&lt;/pre&gt;
&lt;div&gt;
Wie man sehen kann, werden die Unterschiede nicht einfach nur aufgelistet: Wie sein Unix-Vorbild
 &lt;b&gt;diff&lt;/b&gt; liefert auch &lt;b&gt;XMLDIFF&lt;/b&gt; Anweisungen zurück, wie man das erste XML-Dokument in das
 zweite überführen kann. Und ebenso wie das Ergebnis eines Unix &lt;b&gt;diff&lt;/b&gt; mit dem &lt;b&gt;patch&lt;/b&gt; Werkzeug
 auf andere XML-Dokumente angewendet werden kann, kann auch das Ergebnis von &lt;b&gt;XMLDIFF&lt;/b&gt; auf ein neues
 XML-Dokument mit Hilfe von &lt;b&gt;XMLPATCH&lt;/b&gt; angewendet werden. 
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;with&lt;/span&gt; diff &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; (
  &lt;span style="color: blue;"&gt;-- Obiges SELECT XMLDIFF hier ...&lt;/span&gt;
)
&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; xmlpatch(
 xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;document xmlns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text a&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text b&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/document&amp;gt;'&lt;/span&gt;
 ),
 xml_diff
) &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; diff
/ 
&lt;/pre&gt;
&lt;div&gt;
Die zuerst ermittelten XMLDIFF-Anweisungen ...
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Ändere den Text des zweiten XML-Tags &lt;b&gt;tag&lt;/b&gt; innerhalb von &lt;b&gt;document&lt;/b&gt; auf &lt;b&gt;Text 2&lt;/b&gt; &lt;/li&gt;
&lt;li&gt;Hänge innerhalb des Tags &lt;b&gt;document&lt;/b&gt; ein neues Tag &lt;b&gt;tag&lt;/b&gt; mit dem Inhalt &lt;b&gt;Text 3&lt;/b&gt; und dem Attribut &lt;b&gt;option="a"&lt;/b&gt; 
    an.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
... werden auf das im zweiten Parameter übergebene XML-Dokument angewendet. Das Ergebnis sieht in etwa wie folgt aus (die durch XMLPATCH ausgelösten Änderungen sind &lt;span style="color: red;"&gt;rot&lt;/span&gt; markiert):
&lt;/div&gt;
&lt;pre&gt;XMLPATCH
------------------------------------------------------------------------------------------
&amp;lt;document xmlns="my-namespace"&amp;gt;
  &amp;lt;tag&amp;gt;Text a&amp;lt;/tag&amp;gt;
  &amp;lt;tag&amp;gt;&lt;span style="color: red;"&gt;&lt;b&gt;Text 2&lt;/b&gt;&lt;/span&gt;&amp;lt;/tag&amp;gt;
  &lt;span style="color: red;"&gt;&lt;b&gt;&amp;lt;tag xmlns:ns="my-namespace" option="a"&amp;gt;Text 3&amp;lt;/tag&amp;gt;&lt;/b&gt;&lt;/span&gt;
&amp;lt;/document&amp;gt;
&lt;/pre&gt;
&lt;div&gt;
Intern nutzt Oracle die Funktionen auch selbst - speziell für die &lt;i&gt;in Place Schema Evolution&lt;/i&gt; der
 XML DB sind sie wichtig. Allerdings kann man sie auch selbst nutzen, wenn es darum geht, Änderungen an
 einem XML-Dokument zu erkennen und diese ggfs. auf andere Dokumente zu übertragen ...
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions241.htm#CIHFDJAA" target="_blank"&gt;Oracle SQL Language Reference: XMLDIFF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions247.htm#CIHDAEEC" target="_blank"&gt;Oracle SQL Language Reference: XMLPATCH&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;div&gt;
Today I'd like to write something about two interesting SQL functions in the Oracle database: &lt;b&gt;XMLDIFF&lt;/b&gt; 
 and &lt;b&gt;XMLPATCH&lt;/b&gt;. I'll start with &lt;b&gt;XMLDIFF&lt;/b&gt; : As its name indicates - it compares XML documents. I'll illustrate this
 with an example ...
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;document&lt;/span&gt;&lt;span style="color: teal;"&gt; &lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;xmlns&lt;/b&gt;&lt;/span&gt;=&lt;span style="color: magenta;"&gt;"my-namespace"&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;empty-xmltag&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;lt;/empty-xmltag&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;xmltag-content&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;"&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal;"&gt;/xmltag-content&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: teal;"&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;

&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;document&lt;/span&gt;&lt;span style="color: teal;"&gt; &lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;xmlns&lt;/b&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;ns&lt;/b&gt;&lt;/span&gt;=&lt;span style="color: magenta;"&gt;"my-namespace"&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;empty-xmltag&lt;/span&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;xmltag-content&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;quot&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;/ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;xmltag-content&lt;/span&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: teal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: slateblue;"&gt;ns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: teal;"&gt;document&amp;gt;&lt;/span&gt; 
&lt;/pre&gt;
&lt;div&gt;
What do you think? Are these XML documents equal ... or do they differ? This seems to be easy only at the first glance. But let's have &lt;b&gt;XMLDIFF&lt;/b&gt; do the work ...
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; xmldiff(
 xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;document xmlns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;empty-xmltag&amp;gt;&amp;lt;/empty-xmltag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;xmltag-content&amp;gt;"&amp;lt;/xmltag-content&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/document&amp;gt;'&lt;/span&gt;
 ), xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;ns:document xmlns:ns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:empty-xmltag/&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:xmltag-content&amp;gt;&amp;amp;quot;&amp;lt;/ns:xmltag-content&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/ns:document&amp;gt;'&lt;/span&gt;
 )
) &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; dual
/ 

XMLDIFF(XMLTYPE('&amp;lt;DOCUMENTXMLNS="MY-NAMESPACE"&amp;gt;&amp;lt;LEERES-XMLTAG&amp;gt;&amp;lt;/LEERES-XMLTAG&amp;gt;&amp;lt;X
--------------------------------------------------------------------------------
&amp;lt;xd:xdiff xsi:schemaLocation="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt; &lt;a href="http://xmlns/"&gt;http://xmlns&lt;/a&gt;
.oracle.com/xdb/xdiff.xsd" xmlns:xd="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt;" xmln
s:ns="my-namespace" xmlns:xsi="&lt;a href="http://www.w3.org/2001/XMLSchema-instance"&gt;http://www.w3.org/2001/XMLSchema-instance&lt;/a&gt;"&amp;gt;
  &amp;lt;?oracle-xmldiff operations-in-docorder="true" output-model="snapshot" diff-al
gorithm="global"?&amp;gt;
&amp;lt;/xd:xdiff&amp;gt;
&lt;/pre&gt;
&lt;div&gt;
The functions' output indicates that the documents are equal - from the XML point of view. And this
 makes sense since the XML standard allows different markup for the same content. Empty tags, for instance,
 can be expressed as a single tag with a trailing slash (&amp;lt;tag/&amp;gt;) as well as with an opening and a closing
 tag (&amp;lt;tag&amp;gt;&amp;lt;/tag&amp;gt;). Character entities like &amp;amp;quot; have the same meaning as the character itself (").
 And there are more examples beyond these two. So comparing XML documents means more than just comparing
 the text contents - the XML standard must be kept in mind, and &lt;b&gt;XMLDIFF&lt;/b&gt; does exactly this. In the next example
 we'll compare two documents which &lt;i&gt;are&lt;/i&gt; different; also from the "XML point of view". 
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; xmldiff(
 xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;document xmlns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text 1&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text 3&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/document&amp;gt;'&lt;/span&gt;
 ), xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;ns:document xmlns:ns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:tag&amp;gt;Text 1&amp;lt;/ns:tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:tag&amp;gt;Text 2&amp;lt;/ns:tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;ns:tag option="a"&amp;gt;Text 3&amp;lt;/ns:tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/ns:document&amp;gt;'&lt;/span&gt;
 )
) as xml_diff &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; dual
/ 

XML_DIFF
------------------------------------------------------------------------------------------
&amp;lt;xd:xdiff xsi:schemaLocation="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt; &lt;a href="http://xmlns.oracle.co/"&gt;http://xmlns.oracle.co&lt;/a&gt;
m/xdb/xdiff.xsd" xmlns:xd="&lt;a href="http://xmlns.oracle.com/xdb/xdiff.xsd"&gt;http://xmlns.oracle.com/xdb/xdiff.xsd&lt;/a&gt;" xmlns:ns="my-namespace"
xmlns:xsi="&lt;a href="http://www.w3.org/2001/XMLSchema-instance"&gt;http://www.w3.org/2001/XMLSchema-instance&lt;/a&gt;"&amp;gt;
  &amp;lt;?oracle-xmldiff operations-in-docorder="true" output-model="snapshot" diff-algorithm="g
lobal"?&amp;gt;&lt;span style="color: red;"&gt;
  &amp;lt;xd:update-node xd:node-type="text" xd:xpath="/ns:document[1]/ns:tag[2]/text()[1]"&amp;gt;
    &amp;lt;xd:content&amp;gt;Text 2&amp;lt;/xd:content&amp;gt;
  &amp;lt;/xd:update-node&amp;gt;
  &amp;lt;xd:append-node xd:node-type="element" xd:parent-xpath="/ns:document[1]"&amp;gt;
    &amp;lt;xd:content&amp;gt;
      &amp;lt;ns:tag option="a"&amp;gt;Text 3&amp;lt;/ns:tag&amp;gt;
    &amp;lt;/xd:content&amp;gt;
  &amp;lt;/xd:append-node&amp;gt;&lt;/span&gt;
&amp;lt;/xd:xdiff&amp;gt;
&lt;/pre&gt;
&lt;div&gt;
We can see, that &lt;b&gt;XMLDIFF&lt;/b&gt; returns more than just the information that these two documents are
 different. As it's UNIX pendant &lt;b&gt;diff&lt;/b&gt; it returns a "delta" - instructions how to modify
 the first document in order to get the second. This output can be consumed by &lt;b&gt;XMLPATCH&lt;/b&gt;; as we'll see
 in the next example: We'll apply the "patch instruction" to another XML document ...
&lt;/div&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;with&lt;/span&gt; diff &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; (
  &lt;span style="color: blue;"&gt;-- Obiges SELECT XMLDIFF hier ...&lt;/span&gt;
)
&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; xmlpatch(
 xmltype(&lt;span style="color: magenta;"&gt;'&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;document xmlns="my-namespace"&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text a&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;   &amp;lt;tag&amp;gt;Text b&amp;lt;/tag&amp;gt;&lt;/span&gt;
&lt;span style="color: magenta;"&gt;  &amp;lt;/document&amp;gt;'&lt;/span&gt;
 ),
 xml_diff
) &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; diff
/ 
&lt;/pre&gt;
&lt;div&gt;
The "patching" instructions ...
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Modify the text contents of the second tag &lt;b&gt;tag&lt;/b&gt; within &lt;b&gt;document&lt;/b&gt; to &lt;b&gt;Text 2&lt;/b&gt; &lt;/li&gt;
&lt;li&gt;Append another tag &lt;b&gt;tag&lt;/b&gt; containing the text &lt;b&gt;Text 3&lt;/b&gt; and the attrbute &lt;b&gt;option="a"&lt;/b&gt; within &lt;b&gt;document&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
... are now being applied to another XML document which is (in this case) even different
 from the very first one (which we used to compare initially). The output of the &lt;b&gt;XMLPATCH&lt;/b&gt; operation
 is as follows ...
&lt;/div&gt;
&lt;pre&gt;XMLPATCH
------------------------------------------------------------------------------------------
&amp;lt;document xmlns="my-namespace"&amp;gt;
  &amp;lt;tag&amp;gt;Text a&amp;lt;/tag&amp;gt;
  &amp;lt;tag&amp;gt;&lt;span style="color: red;"&gt;&lt;b&gt;Text 2&lt;/b&gt;&lt;/span&gt;&amp;lt;/tag&amp;gt;
  &lt;span style="color: red;"&gt;&lt;b&gt;&amp;lt;tag xmlns:ns="my-namespace" option="a"&amp;gt;Text 3&amp;lt;/tag&amp;gt;&lt;/b&gt;&lt;/span&gt;
&amp;lt;/document&amp;gt;
&lt;/pre&gt;
&lt;div&gt;
&lt;b&gt;XMLDIFF&lt;/b&gt; and &lt;b&gt;XMLPATCH&lt;/b&gt; are used internally by Oracle for the XML DB functionality of &lt;i&gt;In Place XML Schema
 Evolution&lt;/i&gt;. But one can (as we have seen) use them also for own purposes - the functions are interesting when
 it's about comparing XML documents and computing deltas between them.
 einem XML-Dokument zu erkennen und diese ggfs. auf andere Dokumente zu übertragen ...
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions241.htm#CIHFDJAA" target="_blank"&gt;Oracle SQL Language Reference: XMLDIFF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions247.htm#CIHDAEEC" target="_blank"&gt;Oracle SQL Language Reference: XMLPATCH&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-6139405337299966715?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/kFsJw59cVrU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/kFsJw59cVrU/xml-dokumente-mit-sql-vergleichen.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/01/xml-dokumente-mit-sql-vergleichen.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-7868347398587535553</guid><pubDate>Mon, 09 Jan 2012 09:00:00 +0000</pubDate><atom:updated>2012-01-09T10:00:13.725+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">login</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">password</category><category domain="http://www.blogger.com/atom/ns#">user</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">authentication</category><category domain="http://www.blogger.com/atom/ns#">jdbc</category><category domain="http://www.blogger.com/atom/ns#">proxy</category><title>Login als User "A" - mit dem Password von "B": Proxy Authentication!</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;Log in as user "A" - with the password of "B": Proxy Authentication&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;div&gt;
 Es ist in der Tat möglich: Ich kann mich an der Oracle-Datenbank als User "A" mit
 dem Passwort des Benutzers "B" anmelden - und das ist keine Sicherheitslücke. Ich 
 möchte dieses Blog-Posting dem Thema &lt;i&gt;Proxy Authentication&lt;/i&gt; widmen. Das kann man
 ganz besonders in einer dreischichtigen Webarchitektur gebrauchen. Denn dort werden Datenbankverbindungen
 nahezu immer statisch im Application Server konfiguriert ( &lt;i&gt;data-sources.xml&lt;/i&gt;). Wenn
 man in einer solchem Umgebung mit den Nutzerkonten der Datenbank arbeiten möchte, hat
 man ein Problem: Man kann sie nicht alle in der data-sources.xml einrichten; erstmal
 sind es oft zu viele und zweitens kann man die data-sources.xml nicht so einfach im 
 laufenden Betrieb ändern.  Die Lösung ist Proxy Authentication: Dabei wird  die
 Datenbankverbidnung 
 im Application Server fest mit einem technischen User und einem Passwort eingerichtet;
 der tatsächliche Datenbankuser, nach dem sich auch die Privilegien richten, wird
 zur Laufzeit festgelegt. Und das ganze funktioniert wie folgt: Zuerst brauchen wir
 einen technischen User &lt;b&gt;TECHUSER&lt;/b&gt; (mit Passwort &lt;b&gt;TECHUSER&lt;/b&gt;) und zwei "echte" User (&lt;b&gt;REALUSER1&lt;/b&gt; und
 &lt;b&gt;REALUSER2&lt;/b&gt;).
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;user&lt;/font&gt; techuser &lt;font color="#6a5acd"&gt;identified&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; techuser
/

&lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt; &lt;font color="#6a5acd"&gt;to&lt;/font&gt; techuser
/

reate &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser1 &lt;font color="#6a5acd"&gt;identified&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; realuser1
/

&lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt;, &lt;font color="#6a5acd"&gt;resource&lt;/font&gt; &lt;font color="#6a5acd"&gt;to&lt;/font&gt; realuser1
/

reate &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser2 &lt;font color="#6a5acd"&gt;identified&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; realuser2
/

&lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt;, &lt;font color="#6a5acd"&gt;resource&lt;/font&gt; &lt;font color="#6a5acd"&gt;to&lt;/font&gt; realuser2
/
&lt;/pre&gt;
&lt;div&gt;
  Und damit die User in einer Anwendung unterscheidbar werden, bekommen Sie nun eine Kopie
  der &lt;b&gt;EMP&lt;/b&gt;-Tabelle, aber mit unterschiedlichen Inhalten ...
&lt;/div&gt;
&lt;pre&gt;
craete &lt;font color="#6a5acd"&gt;table&lt;/font&gt; realuser1.emp &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; * &lt;font color="#6a5acd"&gt;from&lt;/font&gt; scott.emp &lt;font color="#6a5acd"&gt;where&lt;/font&gt; deptno = &lt;font color="#ff00ff"&gt;10&lt;/font&gt;
/

craete &lt;font color="#6a5acd"&gt;table&lt;/font&gt; realuser2.emp &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; * &lt;font color="#6a5acd"&gt;from&lt;/font&gt; scott.emp &lt;font color="#6a5acd"&gt;where&lt;/font&gt; deptno = &lt;font color="#ff00ff"&gt;20&lt;/font&gt;
/
&lt;/pre&gt;
&lt;div&gt;
 Und jetzt geht es los: Zuerst muss man der Datenbank sagen, dass &lt;b&gt;TECHUSER&lt;/b&gt; die Erlaubnis
 bekommt, sich mit &lt;i&gt;seinem eigenen Passwort&lt;/i&gt; als &lt;b&gt;REALUSER1&lt;/b&gt; oder &lt;b&gt;REALUSER2&lt;/b&gt; "auszugeben". Man kann
 auch sagen: &lt;b&gt;TECHUSER&lt;/b&gt; wird der &lt;i&gt;Proxy User&lt;/i&gt; für die &lt;i&gt;Clients&lt;/i&gt; &lt;b&gt;REALUSER1&lt;/b&gt; und &lt;b&gt;REALUSER2&lt;/b&gt;.
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;alter&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser1 &lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt; through techuser
/

&lt;font color="#804040"&gt;&lt;b&gt;alter&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser2 &lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt; through techuser
/
&lt;/pre&gt;
&lt;div&gt;
 Der Setup lässt sich in der Dictionary View &lt;b&gt;PROXY_USERS&lt;/b&gt; auch überprüfen:
&lt;/div&gt;
&lt;pre&gt;
SQL&amp;gt; select * from proxy_users;

PROXY           CLIENT          AUT FLAGS
--------------- --------------- --- -----------------------------------
TECHUSER        REALUSER1       NO  PROXY MAY ACTIVATE ALL CLIENT ROLES
TECHUSER        REALUSER2       NO  PROXY MAY ACTIVATE ALL CLIENT ROLES
&lt;/pre&gt;
&lt;div&gt;
 Mit SQL*Plus kann man das jetzt schon ausprobieren:
&lt;/div&gt;
&lt;pre&gt;
D:\&amp;gt;sqlplus.exe techuser[realuser1]/techuser

SQL*Plus: Release 11.1.0.6.0 - Production on Do Dez 22 16:17:30 2011

Copyright (c) 1982, 2007, Oracle.  All rights reserved.


Verbunden mit:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options

SQL&amp;gt; select user from dual;

USER
------------------------------
REALUSER1
&lt;/pre&gt;
&lt;div&gt;
 Man sieht sehr schön, dass Username und Passwort des &lt;b&gt;TECHUSER&lt;/b&gt; zum Login
 verwendet werden; in eckigen Klammern wird aber festgelegt, für wen die
 Datenbankverbindung eigentlich aufgemacht werden soll.
&lt;/div&gt;
&lt;div&gt;
 So weit, so gut, so einfach. Aber für eine dreischichtige Applikation nutzt das
 bis jetzt noch gar nichts. Schließlich kann man nicht einfach den "echten" User
 in eckige Klammern in die Definition der Datenbankverbindung eintragen, denn diese
 ist ja statisch. Der User, für den der Connect gelten soll, soll sich aber beliebig
 ändern können - also dynamisch sein. Also müssen wir in der Lage sein, den Usernamen,
 den man bei SQL*Plus in eckige Klammern setzt, per Java-Code zu setzen ... Schauen wir
 uns zunächst ein kleines Java-Testprogramm an: Es gibt zuerst den Namen des angemeldeten
 Users aus ( &lt;b&gt;select user from dual&lt;/b&gt;) und dann die Inhalte der &lt;b&gt;EMP&lt;/b&gt; Tabelle.
 Achtet darauf, dass Username und Passwort des &lt;b&gt;TECHUSER&lt;/b&gt; hart kodiert sind - und das wird
 so bleiben!
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; java.sql.*;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; oracle.jdbc.*;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; java.io.*;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; java.util.*;

&lt;font color="#2e8b57"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/font&gt; proxyConnect {
  &lt;font color="#2e8b57"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt; main(String args[]) &lt;font color="#2e8b57"&gt;&lt;b&gt;throws&lt;/b&gt;&lt;/font&gt; Exception {
    DriverManager.registerDriver(&lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; oracle.jdbc.OracleDriver());
    Connection con = DriverManager.getConnection(&lt;font color="#ff00ff"&gt;&amp;quot;jdbc:oracle:thin:@sccloud030:1521/orcl&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;);
    
&lt;font color="#0000ff"&gt;/*&lt;/font&gt;
&lt;font color="#0000ff"&gt; * Code zum Setzen des Client-Usernamens HIER !!!&lt;/font&gt;
&lt;font color="#0000ff"&gt; */&lt;/font&gt;

    Statement stmt = &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
    ResultSet rs1 = &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
    stmt = con.createStatement();
    rs1 = stmt.executeQuery(&lt;font color="#ff00ff"&gt;&amp;quot;select user from dual&amp;quot;&lt;/font&gt;);
    &lt;font color="#804040"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/font&gt; (rs1.next()) {
      System.out.println(&lt;font color="#ff00ff"&gt;&amp;quot;Database userid: &amp;quot;&lt;/font&gt; + rs1.getString(&lt;font color="#ff00ff"&gt;1&lt;/font&gt;));
    }  
    rs1.close();
    stmt.close();

    stmt = con.createStatement();
    rs1 = stmt.executeQuery(&lt;font color="#ff00ff"&gt;&amp;quot;select * from emp&amp;quot;&lt;/font&gt;);
    &lt;font color="#804040"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/font&gt; (rs1.next()) {
      System.out.println(&lt;font color="#ff00ff"&gt;&amp;quot;EMPNO: &amp;quot;&lt;/font&gt; + rs1.getString(&lt;font color="#ff00ff"&gt;1&lt;/font&gt;) + &lt;font color="#ff00ff"&gt;&amp;quot; [&amp;quot;&lt;/font&gt;+rs1.getString(&lt;font color="#ff00ff"&gt;2&lt;/font&gt;)+&lt;font color="#ff00ff"&gt;&amp;quot;] - DEPTNO: &amp;quot;&lt;/font&gt;+rs1.getString(&lt;font color="#ff00ff"&gt;&amp;quot;DEPTNO&amp;quot;&lt;/font&gt;));
    }  
    rs1.close();
    stmt.close();
    con.close();
  }
} 
&lt;/pre&gt;
&lt;div&gt;
 Beim ersten Test sagt uns das Programm nur, dass wir als &lt;b&gt;TECHUSER&lt;/b&gt; verbunden sind und
 dass es keine &lt;b&gt;EMP&lt;/b&gt;-Tabelle gibt ...
&lt;/div&gt;
&lt;pre&gt;
D:\&amp;gt; java.exe proxyConnect realuser1
Database userid: TECHUSER
Exception in thread "main" java.sql.SQLSyntaxErrorException: 
ORA-00942: Tabelle oder View nicht vorhanden
        at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:91)
        at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:112)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:173)
        :
&lt;/pre&gt;
&lt;div&gt;
 Dann bauen wir jetzt den Code ein, der den "richtigen" User setzt. Tauscht die Zeilen ...
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#0000ff"&gt;/*&lt;/font&gt;
&lt;font color="#0000ff"&gt; * Code zum Setzen des Client-Usernamens HIER !!!&lt;/font&gt;
&lt;font color="#0000ff"&gt; */&lt;/font&gt;
&lt;/pre&gt;
&lt;div&gt;
  ... durch diese hier aus: Als Usernamen nehmen wir den ersten Parameter der Kommandozeile.
&lt;/div&gt;
&lt;pre&gt;
    Properties props = &lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; Properties();
    props.put(&lt;font color="#ff00ff"&gt;&amp;quot;PROXY_USER_NAME&amp;quot;&lt;/font&gt;, args[&lt;font color="#ff00ff"&gt;0&lt;/font&gt;]);
    ((OracleConnection)con).openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);  
&lt;/pre&gt;
&lt;div&gt;
 Neu kompilieren und wieder ausführen. Und .. voilá:
&lt;/div&gt;
&lt;pre&gt;
D:\&amp;gt; java proxyConnect realuser1
Database userid: REALUSER1
EMPNO: 7782 [CLARK] - DEPTNO: 10
EMPNO: 7839 [KING] - DEPTNO: 10
EMPNO: 7934 [MILLER] - DEPTNO: 10

D:\&amp;gt; java proxyConnect realuser2
Database userid: REALUSER2
EMPNO: 7369 [SMITH] - DEPTNO: 20
EMPNO: 7566 [JONES] - DEPTNO: 20
EMPNO: 7788 [SCOTT] - DEPTNO: 20
EMPNO: 7876 [ADAMS] - DEPTNO: 20
EMPNO: 7902 [FORD] - DEPTNO: 20
&lt;/pre&gt;
&lt;div&gt;
 Nur durch die Angabe des Namens wird nun festgelegt, als welcher User die Datenbanksession 
 laufen soll.  Damit kann ein Java-Programm (bspw. in einem Application Server) mit einer statischen
 Datasource-Definition dennoch dynamisch den Datenbankuser wechseln. Denn eine bestehende 
 Proxy-Verbindung kann geschlossen werden, um danach &lt;i&gt;auf der gleichen "physikalischen" Datenbankverbindung&lt;/i&gt;
 eine neue Proxy-Verbindung für einen anderen User zu öffnen. Im folgenden Code
 habe ich das mal illustriert - zur besseren Übersicht habe ich die Datenbankaktionen
 entfernt und gegen den Pseudocall auf &lt;b&gt;erledigeDatenbankaktionen()&lt;/b&gt; ausgetauscht.
&lt;/div&gt;
&lt;pre&gt;
  &lt;font color="#2e8b57"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt; main(String args[]) &lt;font color="#2e8b57"&gt;&lt;b&gt;throws&lt;/b&gt;&lt;/font&gt; Exception {
    &lt;font color="#0000ff"&gt;// Physikalische Verbindung öffnen als TECHUSER&lt;/font&gt;
    DriverManager.registerDriver(&lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; oracle.jdbc.OracleDriver());
    Connection con = DriverManager.getConnection(&lt;font color="#ff00ff"&gt;&amp;quot;jdbc:oracle:thin:@sccloud030:1521/orcl&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;);
    
    &lt;font color="#0000ff"&gt;// Proxy-Verbindung für User REALUSER1 öffnen, etwas tun und schließen&lt;/font&gt;
    Properties props = &lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; Properties();
    props.put(&lt;font color="#ff00ff"&gt;&amp;quot;PROXY_USER_NAME&amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot;realuser1&amp;quot;&lt;/font&gt;);
    ((OracleConnection)con).openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);  
    erledigeDatenbankaktionen(con);
    ((OracleConnection)con).close(OracleConnection.PROXY_SESSION); 

    &lt;font color="#0000ff"&gt;// Die physikalische Verbindung ist immer noch offen ...&lt;/font&gt;
    &lt;font color="#0000ff"&gt;// Proxy-Verbindung für User REALUSER2 öffnen, etwas tun und schließen&lt;/font&gt;
    props.put(&lt;font color="#ff00ff"&gt;&amp;quot;PROXY_USER_NAME&amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot;realuser2&amp;quot;&lt;/font&gt;);
    ((OracleConnection)con).openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);  
    erledigeDatenbankaktionen(con);
    ((OracleConnection)con).close(OracleConnection.PROXY_SESSION); 

    &lt;font color="#0000ff"&gt;// Physikalische Verbindung schließen&lt;/font&gt;
    con.close();
  }
&lt;/pre&gt;
&lt;div&gt;
 Beim Umstieg von Client/Server-
 zu Webanwendungen ist ein solches Vorgehen hochinteressant.
&lt;/div&gt;
&lt;div&gt;
 Wichtig ist, dass &lt;b&gt;REALUSER1&lt;/b&gt; bzw.  &lt;b&gt;REALUSER2&lt;/b&gt; immer noch das &lt;b&gt;CREATE SESSION&lt;/b&gt;-Privileg brauchen; auch
 darf der Account nicht gelockt sein. Es ist aber durchaus möglich, direkte Connects zu unterbinden - 
 dazu muss man "nur" das Passwort auf einen nicht ermittelbaren Wert setzen ...
&lt;/div&gt;
&lt;pre&gt;
SQL&amp;gt; alter user realuser1 identified by values 'Hallo'
&lt;/pre&gt;
&lt;div&gt;
 Nun wird der Text "&lt;b&gt;Hallo&lt;/b&gt;" als Hashwert in die Oracle-Passworttabelle geschrieben - ein Connect als
 &lt;b&gt;REALUSER1&lt;/b&gt; ist nun theoretisch möglich: wenn man das Passwort herausbekommt, dessen Hashwert
 "&lt;b&gt;Hallo&lt;/b&gt;" ergibt. Defacto jedoch kann man sich nur noch über den &lt;b&gt;TECHUSER&lt;/b&gt; als &lt;b&gt;REALUSER1&lt;/b&gt; anmelden. 
 Aber auch ein Parallelbetrieb mit direkten und Proxy-Verbindungen ist natürlich problemlos
 machbar.
&lt;/div&gt;
&lt;div&gt;
 Mehr zur Proxy Authentication in der Dokumentation: Dazu sind zwei Links wichtig:
 &lt;ul&gt;
  &lt;li&gt;Security Guide: Using a Middle Tier Server for Proxy Authentication&lt;br/&gt;
      &lt;a href="http://docs.oracle.com/cd/E11882_01/network.112/e16543/authentication.htm#i1010326" target="_blank"&gt;http://docs.oracle.com/cd/E11882_01/network.112/e16543/authentication.htm#i1010326&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;JDBC Developer's Guide: Proxy Authentication&lt;br/&gt;
  &lt;a href="http://docs.oracle.com/cd/E11882_01/java.112/e16548/proxya.htm#CHDHHAAD" target="_blank"&gt;http://docs.oracle.com/cd/E11882_01/java.112/e16548/proxya.htm#CHDHHAAD&lt;/a&gt;&lt;/li&gt;
 &lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;div&gt;
 Yes - it is possible: You can connect to the Oracle database as say: User "A" with
 the password of User "B" - and that is &lt;i&gt;not&lt;/i&gt; a security vulnerability.  In this
 blog posting I'd like to elaborate a bit on &lt;i&gt;proxy authentication&lt;/i&gt; - this feature
 is particular useful in three-tier-applications. Database connections are typically
 part of the static application server configuration (&lt;i&gt;"data-sources.xml"&lt;/i&gt;).
 And when such a java environments want to use the user accounts in the database
 there is a problem: We cannot add each individual user to the datasource configuration. 
 The first arguments is, that there might be just too many users - the second one is that 
 changes to data-sources.xml are often not possible without downtime.
 So we need a connection using one single technical user's credentials and the ability
 to set the desired username at runtime.
 And that is all what proxy authentication is about. We'll start with creating  
 the technical user (&lt;b&gt;TECHUSER&lt;/b&gt;) and two "real" user accounts (&lt;b&gt;REALUSER1&lt;/b&gt; and &lt;b&gt;REALUSER2&lt;/b&gt;).
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;user&lt;/font&gt; techuser &lt;font color="#6a5acd"&gt;identified&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; techuser
/

&lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt; &lt;font color="#6a5acd"&gt;to&lt;/font&gt; techuser
/

reate &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser1 &lt;font color="#6a5acd"&gt;identified&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; realuser1
/

&lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt;, &lt;font color="#6a5acd"&gt;resource&lt;/font&gt; &lt;font color="#6a5acd"&gt;to&lt;/font&gt; realuser1
/

reate &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser2 &lt;font color="#6a5acd"&gt;identified&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; realuser2
/

&lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt;, &lt;font color="#6a5acd"&gt;resource&lt;/font&gt; &lt;font color="#6a5acd"&gt;to&lt;/font&gt; realuser2
/
&lt;/pre&gt;
&lt;div&gt;
  &lt;b&gt;REALUSER1&lt;/b&gt; and &lt;b&gt;REALUSER2&lt;/b&gt; now get a copy of the &lt;b&gt;EMP&lt;/b&gt; table with different contents: we 
  want to differentiate between the two later on.
&lt;/div&gt;
&lt;pre&gt;
craete &lt;font color="#6a5acd"&gt;table&lt;/font&gt; realuser1.emp &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; * &lt;font color="#6a5acd"&gt;from&lt;/font&gt; scott.emp &lt;font color="#6a5acd"&gt;where&lt;/font&gt; deptno = &lt;font color="#ff00ff"&gt;10&lt;/font&gt;
/

craete &lt;font color="#6a5acd"&gt;table&lt;/font&gt; realuser2.emp &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; * &lt;font color="#6a5acd"&gt;from&lt;/font&gt; scott.emp &lt;font color="#6a5acd"&gt;where&lt;/font&gt; deptno = &lt;font color="#ff00ff"&gt;20&lt;/font&gt;
/
&lt;/pre&gt;
&lt;div&gt;
 Now we declare &lt;b&gt;TECHUSER&lt;/b&gt; as the &lt;i&gt;proxy user&lt;/i&gt; for &lt;b&gt;REALUSER1&lt;/b&gt; and &lt;b&gt;REALUSER2&lt;/b&gt;. This is kind of
 a GRANT statement. The privilege to act as (&lt;i&gt;the clients&lt;/i&gt;) REALUSER1 or REALUSER2 is granted to TECHUSER. 
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#804040"&gt;&lt;b&gt;alter&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser1 &lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt; through techuser
/

&lt;font color="#804040"&gt;&lt;b&gt;alter&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;user&lt;/font&gt; realuser2 &lt;font color="#804040"&gt;&lt;b&gt;grant&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;connect&lt;/font&gt; through techuser
/
&lt;/pre&gt;
&lt;div&gt;
 You might review this in the dictionary view &lt;b&gt;PROXY_USERS&lt;/b&gt;:
&lt;/div&gt;
&lt;pre&gt;
SQL&amp;gt; select * from proxy_users;

PROXY           CLIENT          AUT FLAGS
--------------- --------------- --- -----------------------------------
TECHUSER        REALUSER1       NO  PROXY MAY ACTIVATE ALL CLIENT ROLES
TECHUSER        REALUSER2       NO  PROXY MAY ACTIVATE ALL CLIENT ROLES
&lt;/pre&gt;
&lt;div&gt;
 A first test with SQL*Plus:
&lt;/div&gt;
&lt;pre&gt;
D:\&amp;gt;sqlplus.exe techuser[realuser1]/techuser

SQL*Plus: Release 11.1.0.6.0 - Production on Do Dez 22 16:17:30 2011

Copyright (c) 1982, 2007, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options

SQL&amp;gt; select user from dual;

USER
------------------------------
REALUSER1
&lt;/pre&gt;
&lt;div&gt;
 TECHUSER used his own credentials to log in. But the user &lt;i&gt;as which&lt;/i&gt; the
 connection should be established was provided within the brackets. In SQL*Plus it 
 is that easy: We &lt;i&gt;logged in&lt;/i&gt; as &lt;b&gt;TECHUSER/techuser&lt;/b&gt; and we now &lt;i&gt;are&lt;/i&gt; &lt;b&gt;REALUSER1&lt;/b&gt;.
&lt;/div&gt;
&lt;div&gt;
 So far  - so good. But for real world environments this is virtually useless - no end
 user connects with SQL*Plus. And we cannot add the brackets to the static datasource definition
 in the application server: we need to set the client user dynamically with some code - and
 the following example will show how to do this. First I have a little testing program in
 java language. It first connects to the database with &lt;i&gt;hardcoded&lt;/i&gt; &lt;b&gt;TECHUSER&lt;/b&gt; credentials,
 then it looks up "as who" it is connected and finally it shows the contents of the &lt;b&gt;EMP&lt;/b&gt; table.
 Again: The username and password arguments in the call to &lt;b&gt;DriverManager.getConnection&lt;/b&gt; are 
 hard coded and this will not change!
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; java.sql.*;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; oracle.jdbc.*;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; java.io.*;
&lt;font color="#a020f0"&gt;import&lt;/font&gt; java.util.*;

&lt;font color="#2e8b57"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/font&gt; proxyConnect {
  &lt;font color="#2e8b57"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt; main(String args[]) &lt;font color="#2e8b57"&gt;&lt;b&gt;throws&lt;/b&gt;&lt;/font&gt; Exception {
    DriverManager.registerDriver(&lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; oracle.jdbc.OracleDriver());
    Connection con = DriverManager.getConnection(&lt;font color="#ff00ff"&gt;&amp;quot;jdbc:oracle:thin:@sccloud030:1521/orcl&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;);
    
&lt;font color="#0000ff"&gt;/*&lt;/font&gt;
&lt;font color="#0000ff"&gt; * The java code to set the client username goes here !!!&lt;/font&gt;
&lt;font color="#0000ff"&gt; */&lt;/font&gt;

    Statement stmt = &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
    ResultSet rs1 = &lt;font color="#ff00ff"&gt;null&lt;/font&gt;;
    stmt = con.createStatement();
    rs1 = stmt.executeQuery(&lt;font color="#ff00ff"&gt;&amp;quot;select user from dual&amp;quot;&lt;/font&gt;);
    &lt;font color="#804040"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/font&gt; (rs1.next()) {
      System.out.println(&lt;font color="#ff00ff"&gt;&amp;quot;Database userid: &amp;quot;&lt;/font&gt; + rs1.getString(&lt;font color="#ff00ff"&gt;1&lt;/font&gt;));
    }  
    rs1.close();
    stmt.close();

    stmt = con.createStatement();
    rs1 = stmt.executeQuery(&lt;font color="#ff00ff"&gt;&amp;quot;select * from emp&amp;quot;&lt;/font&gt;);
    &lt;font color="#804040"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/font&gt; (rs1.next()) {
      System.out.println(&lt;font color="#ff00ff"&gt;&amp;quot;EMPNO: &amp;quot;&lt;/font&gt; + rs1.getString(&lt;font color="#ff00ff"&gt;1&lt;/font&gt;) + &lt;font color="#ff00ff"&gt;&amp;quot; [&amp;quot;&lt;/font&gt;+rs1.getString(&lt;font color="#ff00ff"&gt;2&lt;/font&gt;)+&lt;font color="#ff00ff"&gt;&amp;quot;] - DEPTNO: &amp;quot;&lt;/font&gt;+rs1.getString(&lt;font color="#ff00ff"&gt;&amp;quot;DEPTNO&amp;quot;&lt;/font&gt;));
    }  
    rs1.close();
    stmt.close();
    con.close();
  }
} 
&lt;/pre&gt;
&lt;div&gt;
 This program so far does not know anything about proxy connections - the results are
 therefore straightforward: We are connected as &lt;b&gt;TECHUSER&lt;/b&gt; and there is no &lt;b&gt;EMP&lt;/b&gt; table.
&lt;/div&gt;
&lt;pre&gt;
D:\&amp;gt; java.exe proxyConnect realuser1
Database userid: TECHUSER
Exception in thread "main" java.sql.SQLSyntaxErrorException: 
ORA-00942: table or view does not exist.
        at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:91)
        at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:112)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:173)
        :
&lt;/pre&gt;
&lt;div&gt;
 Now we'll add the "magic" lines of code to set the client username. Exchange those three lines ...
&lt;/div&gt;
&lt;pre&gt;
&lt;font color="#0000ff"&gt;/*&lt;/font&gt;
&lt;font color="#0000ff"&gt; * The java code to set the client username goes here !!!&lt;/font&gt;
&lt;font color="#0000ff"&gt; */&lt;/font&gt;
&lt;/pre&gt;
&lt;div&gt;
  ... with these - we'll take the first command line argument as the username.
&lt;/div&gt;
&lt;pre&gt;
    Properties props = &lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; Properties();
    props.put(&lt;font color="#ff00ff"&gt;&amp;quot;PROXY_USER_NAME&amp;quot;&lt;/font&gt;, args[&lt;font color="#ff00ff"&gt;0&lt;/font&gt;]);
    ((OracleConnection)con).openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);  
&lt;/pre&gt;
&lt;div&gt;
 Recompile and test again - and ... it works. 
&lt;/div&gt;
&lt;pre&gt;
D:\&amp;gt; java proxyConnect realuser1
Database userid: REALUSER1
EMPNO: 7782 [CLARK] - DEPTNO: 10
EMPNO: 7839 [KING] - DEPTNO: 10
EMPNO: 7934 [MILLER] - DEPTNO: 10

D:\&amp;gt; java proxyConnect realuser2
Database userid: REALUSER2
EMPNO: 7369 [SMITH] - DEPTNO: 20
EMPNO: 7566 [JONES] - DEPTNO: 20
EMPNO: 7788 [SCOTT] - DEPTNO: 20
EMPNO: 7876 [ADAMS] - DEPTNO: 20
EMPNO: 7902 [FORD] - DEPTNO: 20
&lt;/pre&gt;
&lt;div&gt;
 Only by giving the username on the command line we connected as &lt;b&gt;REALUSER1&lt;/b&gt; or &lt;b&gt;REALUSER2&lt;/b&gt; - the
 password always was &lt;b&gt;TECHUSER&lt;/b&gt;'s one. With this approach a java program can obtain a database
 connection from its application server, set the client username and connect to the
 database as another "real" user. And this proxy connection can be changed while the
 main "physical" connection remains open. The following code shows this - for clarity
 I have removed the actual database actions and replaced them with the
 pseudo method &lt;i&gt;doDatabaseActions()&lt;/i&gt;.
&lt;/div&gt;
&lt;pre&gt;
  &lt;font color="#2e8b57"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt; main(String args[]) &lt;font color="#2e8b57"&gt;&lt;b&gt;throws&lt;/b&gt;&lt;/font&gt; Exception {
    &lt;font color="#0000ff"&gt;// open the physical connection as TECHUSER&lt;/font&gt;
    DriverManager.registerDriver(&lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; oracle.jdbc.OracleDriver());
    Connection con = DriverManager.getConnection(&lt;font color="#ff00ff"&gt;&amp;quot;jdbc:oracle:thin:@sccloud030:1521/orcl&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;,&lt;font color="#ff00ff"&gt;&amp;quot;techuser&amp;quot;&lt;/font&gt;);
    
    &lt;font color="#0000ff"&gt;// open the proxy connection for REALUSER1, do something and close&lt;/font&gt;
    Properties props = &lt;font color="#804040"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt; Properties();
    props.put(&lt;font color="#ff00ff"&gt;&amp;quot;PROXY_USER_NAME&amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot;realuser1&amp;quot;&lt;/font&gt;);
    ((OracleConnection)con).openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);  
    doDatabaseActions(con);
    ((OracleConnection)con).close(OracleConnection.PROXY_SESSION); 

    &lt;font color="#0000ff"&gt;// the physical connection is still open ...&lt;/font&gt;
    &lt;font color="#0000ff"&gt;// now open the proxy connection for REALUSER2, do something and close&lt;/font&gt;
    props.put(&lt;font color="#ff00ff"&gt;&amp;quot;PROXY_USER_NAME&amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot;realuser2&amp;quot;&lt;/font&gt;);
    ((OracleConnection)con).openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);  
    doDatabaseActions(con);
    ((OracleConnection)con).close(OracleConnection.PROXY_SESSION); 

    &lt;font color="#0000ff"&gt;// finally close the physical connection&lt;/font&gt;
    con.close();
  }
&lt;/pre&gt;
&lt;div&gt;
 When client/server applications are moving to a web environment,
 this technology gets highly interesting - because the application can keep its existing
 user, role and security model and move on to the web technology where all database connections 
 are done with one technical user.
&lt;/div&gt;
&lt;div&gt;
 &lt;b&gt;REALUSER1&lt;/b&gt; or &lt;b&gt;REALUSER2&lt;/b&gt; still need their &lt;b&gt;CREATE SESSION&lt;/b&gt; privilege - the accounts also
 &lt;i&gt;must&lt;/i&gt; exist in the database and must not be locked. But (if needed) you actually can "forbid"
 direct connections by setting the password to an "impossible" value ...
&lt;/div&gt;
&lt;pre&gt;
SQL&amp;gt; alter user realuser1 identified by values 'Hello'
&lt;/pre&gt;
&lt;div&gt;
 The &lt;b&gt;REALUSER1&lt;/b&gt; account is still open and connects are possible in theory. But since the
 &lt;b&gt;IDENTIFIED BY VALUES&lt;/b&gt; command directly wrote "&lt;b&gt;Hello&lt;/b&gt;" into the password table, one would
 have to find out one of the password - which evaluate to "&lt;b&gt;Hello&lt;/b&gt;" during the hashing process - I'll 
 say it that way: at least very difficult. Connections as &lt;b&gt;REALUSER1&lt;/b&gt; now are only possible as
 connections through &lt;b&gt;TECHUSER&lt;/b&gt;. But it is also possible to have both direct and proxy connections 
 in parallel.
&lt;/div&gt;
&lt;div&gt;
 More about proxy authentication is in the documentation:
 &lt;ul&gt;
  &lt;li&gt;Security Guide: Using a Middle Tier Server for Proxy Authentication&lt;br/&gt;
      &lt;a href="http://docs.oracle.com/cd/E11882_01/network.112/e16543/authentication.htm#i1010326" target="_blank"&gt;http://docs.oracle.com/cd/E11882_01/network.112/e16543/authentication.htm#i1010326&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;JDBC Developer's Guide: Proxy Authentication&lt;br/&gt;
  &lt;a href="http://docs.oracle.com/cd/E11882_01/java.112/e16548/proxya.htm#CHDHHAAD" target="_blank"&gt;http://docs.oracle.com/cd/E11882_01/java.112/e16548/proxya.htm#CHDHHAAD&lt;/a&gt;&lt;/li&gt;
 &lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-7868347398587535553?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/AkiS4pi1dMM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/AkiS4pi1dMM/login-als-user-mit-dem-password-von-b.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>2</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2012/01/login-als-user-mit-dem-password-von-b.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-197401508026736516</guid><pubDate>Thu, 22 Dec 2011 16:24:00 +0000</pubDate><atom:updated>2011-12-22T17:26:02.749+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">oracle414</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>Zum Ende von 2011: Oracle 4.1.4 ...</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;At the end of 2011: Oracle 4.1.4&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;div&gt;
Das letzte Blog Posting in 2011 soll nichts technisches mehr sein - die letzten Tage im 
 Jahr kann man ja ein wenig zur Ruhe kommen. Daher hier nur ein paar Screenshots, die
 ich gemacht habe, als ich eine alte Oracle 4.1.4 nochmals installiert habe. Kein XML, kein
 PL/SQL, kein Oracle TEXT, kein APEX ... aber EMP ... und DEPT!
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-biV4NRKqvuI/TvNZhunXALI/AAAAAAAAAJk/JYNDaB1fCE4/s1600/ora414-1.png" imageanchor="1"&gt;&lt;img border="0" height="214" src="http://3.bp.blogspot.com/-biV4NRKqvuI/TvNZhunXALI/AAAAAAAAAJk/JYNDaB1fCE4/s320/ora414-1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-xMV4rvnM_Z8/TvNZlJMT00I/AAAAAAAAAJw/XPk2tU1GVVQ/s1600/ora414-2.png" imageanchor="1"&gt;&lt;img border="0" height="214" src="http://1.bp.blogspot.com/-xMV4rvnM_Z8/TvNZlJMT00I/AAAAAAAAAJw/XPk2tU1GVVQ/s320/ora414-2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Frohe Weihnachten und ein gutes neues Jahr 2012!&lt;/b&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;div&gt;
My last blog posting in 2011 will not contain technical stuff. The last few days in a
 year are a good chance to relax a bit - and so I just would like to post some screenshots
 which I have taken while installing the Oracle 4.1.4 files which I found a couple of weeks ago.
 No XML, no PL/SQL, no Oracle TEXT, no APEX ... but EMP ... and DEPT.
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-biV4NRKqvuI/TvNZhunXALI/AAAAAAAAAJk/JYNDaB1fCE4/s1600/ora414-1.png" imageanchor="1"&gt;&lt;img border="0" height="214" src="http://3.bp.blogspot.com/-biV4NRKqvuI/TvNZhunXALI/AAAAAAAAAJk/JYNDaB1fCE4/s320/ora414-1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-xMV4rvnM_Z8/TvNZlJMT00I/AAAAAAAAAJw/XPk2tU1GVVQ/s1600/ora414-2.png" imageanchor="1"&gt;&lt;img border="0" height="214" src="http://1.bp.blogspot.com/-xMV4rvnM_Z8/TvNZlJMT00I/AAAAAAAAAJw/XPk2tU1GVVQ/s320/ora414-2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Merry Christmas and a happy new year 2012!&lt;/b&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-197401508026736516?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/k5Q4Fi-RUNk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/k5Q4Fi-RUNk/zum-ende-von-2011-oracle-414.html</link><author>noreply@blogger.com (Carsten Czarski)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-biV4NRKqvuI/TvNZhunXALI/AAAAAAAAAJk/JYNDaB1fCE4/s72-c/ora414-1.png" height="72" width="72" /><thr:total>0</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/12/zum-ende-von-2011-oracle-414.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-235489401723484321</guid><pubDate>Wed, 07 Dec 2011 15:39:00 +0000</pubDate><atom:updated>2011-12-08T14:38:45.990+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">analytic function</category><category domain="http://www.blogger.com/atom/ns#">ratio_to_report</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>Anteile in Prozent in einem Bericht kalkulieren - nur mit SQL!</title><description>&lt;div lang="en" style="color: #cc6600; display: none;"&gt;
How to calculate "ratio to report" in SQL&lt;/div&gt;
&lt;div lang="de"&gt;
Heute morgen erreichte mich eine SQL-Frage - und das Problem taucht sicherlich öfter auf,
 daher veröffentliche ich meine Antwort hier für alle. Ausgangspunkt ist eine Tabelle.
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;|art   |anzahl     |kosten       |anteil    |
|------|-----------|-------------------------
| A    |        55 |       16,95 |     null |
| B    |        55 |        5,45 |     null |
| C    |        55 |        3,20 |     null |
| D    |        55 |        1,95 |     null |
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Die rechte Spalte &lt;b&gt;anteil&lt;/b&gt; soll nun den prozentualen (hier:) Kostenanteil der Zeile im
 Verhältnis zur Summe über alle Zeilen enthalten. Damit ich die Tabelle nicht neu anlegen
 muss, übertrage ich das Beispiel auf die uns allen bekannte Tabelle &lt;b&gt;EMP&lt;/b&gt;: Wir wollen
 also zu jeder das Gehalt als prozentualen Anteil  an der Gesamt-Gehaltssumme ausgedrückt
 sehen. Fangen wir mit dem "klassischen" Ansatz an ...
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;with&lt;/span&gt; summe &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; (
  &lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; sum(sal) sal &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp
)
&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.sal,
  e.sal / s.sal * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; anteil
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e, summe s
/ 

ENAME            SAL  ANTEIL
---------- --------- -------
SMITH           1280    2,76
ALLEN           2560    5,51
WARD            2000    4,31
JONES           4760   10,25
MARTIN          2000    4,31
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Diese Lösung dürfte auf nahezu allen Datenbanksystemen funktionieren - mit der &lt;b&gt;WITH&lt;/b&gt;-Klausel
 wird zunächst die Gehaltsumme ermittelt und dann per Join in die eigentliche Abfrage
 integriert. Wenn man den Gehaltsanteil pro Abteilung (&lt;b&gt;DEPTNO&lt;/b&gt;) sehen möchte, müsste man
 die Abfrage in der WITH-Klausel mit einem &lt;b&gt;GROUP BY&lt;/b&gt; versehen und eine Joinbedingung in
 die Hauptabfrage einbauen ...
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;with&lt;/span&gt; summe &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; (
  &lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; deptno, sum(sal) sal &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp
  &lt;span style="color: slateblue;"&gt;group&lt;/span&gt; &lt;span style="color: slateblue;"&gt;by&lt;/span&gt; deptno
)
&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  e.sal / s.sal * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; anteil_dept
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e join  summe s &lt;span style="color: slateblue;"&gt;on&lt;/span&gt; (e.deptno = s.deptno)
/

ENAME          DEPTNO       SAL ANTEIL_DEPT
---------- ---------- --------- -----------
SMITH              20      1280        7,36
ALLEN              30      2560       17,02
WARD               30      2000       13,30
JONES              20      4760       27,36
MARTIN             30      2000       13,30
BLAKE              30      4560       30,32
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
So weit - so gut. Aber es geht auch wesentlich schöner: Setzt man analytische
 Funktionen ein, so kann man sich die Inline-View sparen - das macht dann alles
 die Datenbank ... so könnte man die analytische Variante von &lt;b&gt;SUM&lt;/b&gt; wie folgt verwenden.
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  (e.sal / sum(sal) over ()) * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; anteil
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/
ENAME          DEPTNO       SAL  ANTEIL
---------- ---------- --------- -------
SMITH              20      1280    2,76
ALLEN              30      2560    5,51
WARD               30      2000    4,31
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Hier wird &lt;b&gt;SUM&lt;/b&gt; &lt;i&gt;ohne&lt;/i&gt; &lt;b&gt; GROUP BY&lt;/b&gt; verwendet - einfach weil es die analytische Variante
 ist. Das sog. &lt;i&gt;Query Window&lt;/i&gt;, welches angibt, über welche Zeilen das Aggregat
 gebildet werden soll, wird in der &lt;b&gt;OVER&lt;/b&gt; -Klausel festgelegt. Und wenn die Klammern 
 leer sind, heißt das soviel wie "über alles". Aber auch die Variante mit den
 Anteil pro Abteilung ist machbar.
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  (e.sal / sum(sal) over (partition &lt;span style="color: slateblue;"&gt;by&lt;/span&gt; deptno)) * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; anteil
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/

ENAME          DEPTNO       SAL  ANTEIL
---------- ---------- --------- -------
CLARK              10      3920   28,00
KING               10      8000   57,14
MILLER             10      2080   14,86
JONES              20      4760   27,36
FORD               20      4800   27,59
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Jetzt steht etwas in der OVER()-Klausel drin. Mit &lt;b&gt;PARTITION BY&lt;/b&gt; wird festgelegt, dass
 das Aggregat (die Summe) nach Abteilungen berechnet werden soll. Das Schlüsselwort
 PARTITION BY ist übrigens &lt;i&gt;nicht&lt;/i&gt; zu verwechseln mit der Tabellenpartitionierung und 
 im Gegensatz zu dieser erfordern die analytischen Funktionen keine separaten Lizenzen.
 Aber es geht sogar noch einfacher: Denn für diese Aufgabe gibt es eine spezielle
 analytische Funktion: &lt;b&gt;RATIO_TO_REPORT&lt;/b&gt;.
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  ratio_to_report(e.sal) over () * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; anteil
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/

ENAME          DEPTNO        SAL  ANTEIL
---------- ---------- ---------- -------
SMITH              20       1280    2,76
ALLEN              30       2560    5,51
WARD               30       2000    4,31
JONES              20       4760   10,25
MARTIN             30       2000    4,31
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Und natürlich geht auch hier die &lt;b&gt;PARTITION BY&lt;/b&gt;-Klausel ...
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  ratio_to_report(e.sal) over (partition &lt;span style="color: slateblue;"&gt;by&lt;/span&gt; deptno) * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; anteil
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Analytische Funktionen lohnen auf jeden Fall eine genauere Betrachtung. Jeder, der mit
 SQL und der Oracle-Datenbanken arbeitet, sollte sie kennen. Neben den hier beschriebenen
 Dingen lassen sich damit auch gleitende Durchschnitte, fortlaufende Summen, Rankings und
 andere Dinge, die sonst recht kompliziertes SQL mit Subselects erfordern, mit einfachen Funktionsaufrufen 
 erledigen. Zum Nachlesen ist hier noch ein &lt;a href="http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm#i81407" target="_blank"&gt;Link zur Dokumentation&lt;/a&gt;.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
This morning I got a SQL question - nothing difficult - but I think, this kind of requirement
 is more frequent, and therefore I decided to publish the answer for everyone. The question
 is based on table data (as always) ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;|art   |count      |cost         |cost_share |
|------|-----------|--------------------------
| A    |        55 |       16,95 |      null |
| B    |        55 |        5,45 |      null |
| C    |        55 |        3,20 |      null |
| D    |        55 |        1,95 |      null |
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
The right column cost_share should contain the row's share of total cost - expressed in percent. So
 the cost column needs to be divided by &lt;b&gt;SUM(COST)&lt;/b&gt; over all rows. I'm lazy: so instead of creating
 this table I decided to solve the problem  for the &lt;b&gt;SAL&lt;/b&gt; column in the well known &lt;b&gt;EMP&lt;/b&gt; table. 
 Let's start with "classic" SQL.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;with&lt;/span&gt; total &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; (
  &lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; sum(sal) sal &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp
)
&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.sal,
  e.sal / s.sal * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; share
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e, total s
/ 

ENAME            SAL   SHARE
---------- --------- -------
SMITH           1280    2,76
ALLEN           2560    5,51
WARD            2000    4,31
JONES           4760   10,25
MARTIN          2000    4,31
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
This query should work on almost every database system. First we compute the total
 salary amount with an &lt;i&gt;inline view&lt;/i&gt; using the &lt;b&gt;WITH&lt;/b&gt; clause. This inline view
 will be joined in the main query. It returns only one row, so we don't need any
 join criteria and we can access the total salary amount just like a table column. And
 this can be extended - if we'd like to see the salary share expressed as "&lt;i&gt;percentage of the 
 department total&lt;/i&gt;",
 we add a &lt;b&gt;GROUP BY&lt;/b&gt; to the inline view and extend the join in the main query as follows ... 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;with&lt;/span&gt; total &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; (
  &lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; deptno, sum(sal) sal &lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp
  &lt;span style="color: slateblue;"&gt;group&lt;/span&gt; &lt;span style="color: slateblue;"&gt;by&lt;/span&gt; deptno
)
&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  e.sal / s.sal * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; share_dept
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e join  total s &lt;span style="color: slateblue;"&gt;on&lt;/span&gt; (e.deptno = s.deptno)
/

ENAME          DEPTNO       SAL  SHARE_DEPT
---------- ---------- --------- -----------
SMITH              20      1280        7,36
ALLEN              30      2560       17,02
WARD               30      2000       13,30
JONES              20      4760       27,36
MARTIN             30      2000       13,30
BLAKE              30      4560       30,32
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
So far, so good. This works, but there are much more elegant approaches. Now I'll
 drop my inline view and use the &lt;span class="italicbodycopy"&gt;analytic variant&lt;/span&gt; 
 of &lt;b&gt;SUM()&lt;/b&gt; for the problem. 
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  (e.sal / sum(sal) over ()) * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; share
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/
ENAME          DEPTNO       SAL   SHARE
---------- ---------- --------- -------
SMITH              20      1280    2,76
ALLEN              30      2560    5,51
WARD               30      2000    4,31
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
This query uses &lt;b&gt;SUM&lt;/b&gt; &lt;i&gt;without&lt;/i&gt; &lt;b&gt;GROUP BY&lt;/b&gt;, because it's the &lt;i&gt;analytic&lt;/i&gt; SUM function. 
 The &lt;i&gt;query window&lt;/i&gt; ,
 which defines the rows to be aggregated, is specified in the &lt;b&gt;OVER()&lt;/b&gt; clause. The aggregate
 is then calculated to each row of the query result set. An empty OVER clause means as much
 as "over all rows". But we can also do the calculation on the department level.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  (e.sal / sum(sal) over (partition &lt;span style="color: slateblue;"&gt;by&lt;/span&gt; deptno)) * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; share
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/

ENAME          DEPTNO       SAL   SHARE
---------- ---------- --------- -------
CLARK              10      3920   28,00
KING               10      8000   57,14
MILLER             10      2080   14,86
JONES              20      4760   27,36
FORD               20      4800   27,59
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Now we have the keywords &lt;b&gt;PARTITION BY&lt;/b&gt; inside the OVER() clause. So the aggregate
 is being computed for each department.  &lt;i&gt;Don't confuse&lt;/i&gt; this PARTITION BY clause 
 with table partitioning. Opposed to the latter, PARTITION BY
 within an analytic function has nothing to do with table storage and does not
 require an additional license. But we can solve the original problem even more
 elegant. Why? Because there is a special function for this purpose: &lt;b&gt;RATIO_TO_REPORT&lt;/b&gt;.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  ratio_to_report(e.sal) over () * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; share
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/

ENAME          DEPTNO        SAL   SHARE
---------- ---------- ---------- -------
SMITH              20       1280    2,76
ALLEN              30       2560    5,51
WARD               30       2000    4,31
JONES              20       4760   10,25
MARTIN             30       2000    4,31
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
And this (of course) also works with &lt;b&gt;PARTITION BY&lt;/b&gt; ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  e.ename, 
  e.deptno,
  e.sal,
  ratio_to_report(e.sal) over (partition &lt;span style="color: slateblue;"&gt;by&lt;/span&gt; deptno) * &lt;span style="color: magenta;"&gt;100&lt;/span&gt; share
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; emp e
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Analytic functions are absolutely worth the learing effort. Beyond the problem described here,
 analytic functions provide an  easy query syntax for things like moving averages, rankings or
 other aggregates with flexible query windows. Solving this with "classic" SQL is possible (of course),
 but this most often gets cumbersome and difficult to read. You'll find more information in the
 &lt;a href="http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm#i81407" target="_blank"&gt;documentation&lt;/a&gt;.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-235489401723484321?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/xJ1LrF9tdP4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/xJ1LrF9tdP4/how-to-calculate-ratio-to-report-in-sql.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>1</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1448353 11.5580067</georss:point><georss:box>47.9753153 11.2421497 48.314355299999995 11.8738637</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/12/how-to-calculate-ratio-to-report-in-sql.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-8980919228893107418</guid><pubDate>Mon, 21 Nov 2011 10:45:00 +0000</pubDate><atom:updated>2011-11-22T08:34:44.481+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sure</category><category domain="http://www.blogger.com/atom/ns#">truncate</category><category domain="http://www.blogger.com/atom/ns#">drop</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">table</category><title>DROP TABLE .. Sind Sie sicher?</title><description>&lt;div lang="en" style="color: #cc6600; display: none;"&gt;
"Are you sure?" for DROP TABLE&lt;/div&gt;
&lt;div lang="de" style="border: 1px solid black; margin-left: 1cm; padding: 3px;"&gt;
&lt;i&gt;UPDATE:&lt;/i&gt; Auf einem internen "Produktionsserver" (sofern man davon sprechen kann) habe ich das Package natürlich gleich installiert. Und heute morgen dann gemerkt, dass ein TRUNCATE / DROP auch mal der Normalfall sein kann. Als ich mich im APEX-Workspace einloggen wollte, kam die Fehlermeldung, dass ein DROP / TRUNCATE auf die Tabelle WWV_FLOW_USER_ACCESS_LOG2$ nicht möglich ist. APEX macht das von sich aus: &lt;b&gt;Da hilft es nix: Der Trigger muss erweitert werden!&lt;/b&gt; Ich habe den Code (unten) angepasst und eine Ausnahme für APEX eingebaut; es kann durchaus sein, dass noch ein paar hinzukommen. Wenn euch da etwas vor mir auffällt, einfach in den Kommentar schreiben.&lt;/div&gt;
&lt;div lang="de"&gt;
Jüngst bin ich nochmals über das Thema &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e25519/triggers.htm#i1007895"&gt;Database Event Triggers mit PL/SQL&lt;/a&gt; gestolpert - man kann
 ja (schon seit einiger Zeit) auch Trigger auf Datenbank-Events anlegen - ein klassisches Beispiel
 wäre das "Verbieten" einer DROP-Operation auf Produktionssystemen - einfach zur Sicherheit. Der Trigger
 dazu ist einfach und schnell gebaut ...
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: slateblue;"&gt;trigger&lt;/span&gt; tr_drop_is_prohibited
before &lt;span style="color: #804040;"&gt;&lt;b&gt;drop&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;on&lt;/span&gt; database
&lt;span style="color: slateblue;"&gt;begin&lt;/span&gt;
  raise_application_error(&lt;span style="color: magenta;"&gt;-20000&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'DROP IS NOT ALLOWED ON THIS SYSTEM'&lt;/span&gt;);
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt;;
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Einfach, aber effektvoll. Man kann nun auf dieser Datenbank nichts mehr droppen (außer dem 
 Trigger selbst, natürlich). Aber für den praktischen Einsatz etwas zu "grobstollig". Erstens 
 ist ein TRUNCATE Table mittlerweile schlimmer als ein DROP TABLE, welches man mit dem Recycle Bin
 (FLASHBACK TABLE ... TO BEFORE DROP) rückgängig machen kann, zum anderen muss es ja manchmal doch
 sein, dass man etwas droppen will ... und dann muss man erst den Trigger deaktivieren und danach wieder
 aktivieren. 
&lt;/div&gt;
&lt;div lang="de"&gt;
Nach diesem Gedanken kam ich auf die Idee, eine Art "Sind Sie Sicher?"-Mechanismus für 
 DROP- und TRUNCATE-Operationen zu bauen. In der Datenbank funktioniert er nur andersherum als bei Microsoft
 Windows: Man muss die Drop-Operation zuerst deklarieren und dann ausführen. Auf einem Produktionssystem
 ist sowas vielleicht doch ganz hilfreich und erspart unter Umständen das eine oder andere versehentlich
 gedroppte Object. Hier ist nun der Code (muss als SYS eingespielt werden) - wir beginnen mit einem
 Package, mit dem die DROP-Operation vorher deklariert wird: 
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;replace&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt; PREDROP &lt;span style="color: #804040;"&gt;&lt;b&gt;authid&lt;/b&gt;&lt;/span&gt; current_user &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  g_forsession &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
  g_nextobject &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
  g_objectname &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;''&lt;/span&gt;;
  g_objecttype &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;''&lt;/span&gt;;
  g_objectuser &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;''&lt;/span&gt;;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj(
    p_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;,
    p_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: teal;"&gt;user&lt;/span&gt;,
    p_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TABLE'&lt;/span&gt;
  );
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; sess(
    p_enable &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;
  );
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; clear; 
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; info;
&lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; PREDROP;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
sho err

&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;replace&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;body&lt;/b&gt;&lt;/span&gt; PREDROP &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; sess (
    p_enable &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;
  ) &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt; 
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
     g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_enable;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; sess;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;;

    g_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; obj;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj (
    p_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;,
    p_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: teal;"&gt;user&lt;/span&gt;,
    p_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TABLE'&lt;/span&gt;
  ) &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;;
    g_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_objectname;
    g_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_objecttype;
    g_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_objectuser;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; obj;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; clear &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; clear;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; info &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'********************************************'&lt;/span&gt;);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Enable Session Flag: '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: #804040;"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/span&gt; g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TRUE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'FALSE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;));
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Enable Object Flag:  '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: #804040;"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/span&gt; g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TRUE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'FALSE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;));
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Object name:         '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;g_objectname);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Object type:         '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;g_objecttype);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Object owner:        '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;g_objectuser);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'********************************************'&lt;/span&gt;);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;''&lt;/span&gt;);
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; info;
&lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; PREDROP;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
sho err

&lt;span style="color: teal;"&gt;grant&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;execute&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;on&lt;/span&gt; PREDROP &lt;span style="color: teal;"&gt;to&lt;/span&gt; &lt;span style="color: teal;"&gt;public&lt;/span&gt;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;

&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: teal;"&gt;public&lt;/span&gt; &lt;span style="color: teal;"&gt;synonym&lt;/span&gt; PREDROP &lt;span style="color: #804040;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; sys.PREDROP
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Execute-Privileg und Public Synonym nicht vergessen und dann geht es auch schon
 weiter. Als nächstes kommt der Database Event Trigger, der ins Package hineinguckt,
 ob das Objekt, was da gerade bearbeitet werden soll, vorher deklariert wurde - wenn ja,
 geht die Operation durch, wenn nicht, wird ein Fehler ausgelöst ...
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;trigger&lt;/font&gt; tr_drop_protection 
before &lt;font color="#804040"&gt;&lt;b&gt;drop&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;truncate&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;on&lt;/font&gt; database
declare
  l_raiseerror     &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;

  l_namematch      &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_typematch      &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_usermatch      &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_match          &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_always_allowed &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;

  &lt;font color="#0000ff"&gt;/* UPDATE: &lt;/font&gt;
&lt;font color="#0000ff"&gt;   * Some code need to be allowed in general!&lt;/font&gt;
&lt;font color="#0000ff"&gt;   */&lt;/font&gt; 
  &lt;font color="#6a5acd"&gt;function&lt;/font&gt; always_allowed(p_owner &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;, p_object &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;) &lt;font color="#6a5acd"&gt;return&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;is&lt;/font&gt;
    l_always &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  &lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; p_owner &lt;font color="#804040"&gt;&lt;b&gt;like&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'APEX_%'&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; p_object &lt;font color="#804040"&gt;&lt;b&gt;like&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'WWV_FLOW_%LOG%'&lt;/font&gt; &lt;font color="#6a5acd"&gt;then&lt;/font&gt;
      l_always := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;
      goto ende;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;
    &amp;lt;&amp;lt;ende&amp;gt;&amp;gt;
    &lt;font color="#6a5acd"&gt;return&lt;/font&gt; l_always;
  &lt;font color="#6a5acd"&gt;end&lt;/font&gt; always_allowed;

  &lt;font color="#6a5acd"&gt;function&lt;/font&gt; match(p_string1 &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;, p_string2 &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;) &lt;font color="#6a5acd"&gt;return&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;is&lt;/font&gt;
    l_match &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  &lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; p_string1 = p_string2 &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; p_string2 &lt;font color="#6a5acd"&gt;is&lt;/font&gt; &lt;font color="#6a5acd"&gt;null&lt;/font&gt; &lt;font color="#6a5acd"&gt;then&lt;/font&gt; 
      l_match := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;else&lt;/font&gt; 
      l_match := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;return&lt;/font&gt; l_match;
  &lt;font color="#6a5acd"&gt;end&lt;/font&gt; match;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
    l_namematch := match(ora_dict_obj_name, PREDROP.g_objectname);
    l_typematch := match(ora_dict_obj_type, PREDROP.g_objecttype);
    l_usermatch := match(ora_dict_obj_owner, PREDROP.g_objectuser);
    l_match := l_namematch &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; l_usermatch &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; l_typematch;
    l_always_allowed := always_allowed(ora_dict_obj_owner, ora_dict_obj_name);

    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; ((PREDROP.g_nextobject &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; PREDROP.g_forsession) &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; l_match) &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; l_always_allowed  &lt;font color="#6a5acd"&gt;then&lt;/font&gt;
      l_raiseerror := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;else&lt;/font&gt;
      l_raiseerror := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;

    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/font&gt; PREDROP.g_forsession &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/font&gt; l_raiseerror &lt;font color="#6a5acd"&gt;then&lt;/font&gt; 
      PREDROP.clear;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;

    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; l_raiseerror &lt;font color="#6a5acd"&gt;then&lt;/font&gt;
      raise_application_error(&lt;font color="#ff00ff"&gt;-20000&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'Enable DROP/TRUNCATE of '&lt;/font&gt;||ora_dict_obj_type|| &lt;font color="#ff00ff"&gt;' &amp;quot;'&lt;/font&gt;||ora_dict_obj_name||&lt;font color="#ff00ff"&gt;'&amp;quot; with the '&lt;/font&gt;||upper(&lt;font color="#ff00ff"&gt;'PREDROP'&lt;/font&gt;)||&lt;font color="#ff00ff"&gt;' package.'&lt;/font&gt;);
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Und das war's auch schon. Von jetzt an funktioniert DROP und TRUNCATE etwas anders ...
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;pre&gt;SQL&amp;gt; drop table emp3;
drop table emp3
*
FEHLER in Zeile 1:
ORA-00604: Fehler auf rekursiver SQL-Ebene 1
ORA-20000: Enable DROP/TRUNCATE of TABLE "EMP3" with the PREDROP package.
ORA-06512: in Zeile 36

SQL&amp;gt; exec predrop.obj('EMP3');

PL/SQL-Prozedur erfolgreich abgeschlossen.

SQL&amp;gt; drop table emp3;

Tabelle wurde gelöscht.

SQL&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Für Truncate gilt das gleiche. Lässt man den Objektnamen auf SQL NULL, gilt die Freigabe für die
 nächste Tabelle, egal, wie sie heißt.  Setzt man auch den Object Type auf SQL NULL, gilt die
 Freigabe für alle Objekte im Schema. Und der Parameter P_OBJECTUSER gilt analog. Ruft man dann
 noch die Prozedur PREDROP.SESS auf, gilt die Freigabe nicht nur für das nächste Objekt, sondern
 für die ganze Session. Auch auf Produktionsungebungen läuft ja mal ein Skript mit mehreren
 &lt;i&gt;gewollten&lt;/i&gt; DROP-Operationen - solche Vorgänge sollten nicht behindert werden; das Package
 soll helfen und nicht im Weg sehen.
 Man könnte das jetzt natürlich auch noch mit regulären Ausdrücken erweitern und so die völlige
 Flexibilität bekommen - aber das machen wir ein anderes Mal ...
&lt;/div&gt;
&lt;div lang="de"&gt;
Was denkt Ihr ...?
&lt;/div&gt;
&lt;div lang="en" style="display: none; border: 1px solid black; margin-left: 1cm; padding: 3px;"&gt;
&lt;i&gt;UPDATE:&lt;/i&gt; Just yesterday I installed this package on my own "production" instance - and as  I wanted to login into APEX today I encountered my own message &lt;b&gt;Cannot DROP/TRUNCATE table "WWV_FLOW_USER_ACCESS_LOG2$"&lt;/b&gt; - so APEX does some regular DROP / TRUNCATE operations which must not be trapped by the Trigger - So I extended the trigger code a bit (further extensions might be necessary in the future) - just have a look into the new trigger code. If you also encounter DROP or TRUNCATE operations which need to ge generally allowed in the trigger, feel free to post me a message or a comment.&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Recently I again encountered the &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e25519/triggers.htm#i1007895"&gt;database event triggers&lt;/a&gt; in PL/SQL - using these you can place a trigger not only on table or view DML, but
 also on DDL commands or database events like STARTUP, SHUTDOWN oder LOGON. One thirst thought would be prohibiting
 the DROP operation on a production instance - the trigger code for this is rather simple ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: slateblue;"&gt;trigger&lt;/span&gt; tr_drop_is_prohibited
before &lt;span style="color: #804040;"&gt;&lt;b&gt;drop&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;on&lt;/span&gt; database
&lt;span style="color: slateblue;"&gt;begin&lt;/span&gt;
  raise_application_error(&lt;span style="color: magenta;"&gt;-20000&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'DROP IS NOT ALLOWED ON THIS SYSTEM'&lt;/span&gt;);
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt;;
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Simple and powerful. On this instance no object can be dropped any more (except the trigger itself, of course). 
 But this can also lead to a lot of problems, of course: Even on production systems, sometimes there &lt;i&gt;must&lt;/i&gt;
 be dropped something. Then the trigger needs to be disabled before and enabled after the operation. And then
 there might be objects which are frequently dropped and re-created and other objects which not. And what about
 the TRUNCATE operation. This one cannot be undone with FLASHBACK TABLE TO BEFORE DROP - so accidentially use
 of TRUNCATE is much more dangerous than the DROP operation ... 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
So my next thought was to try a bit more sophisticated approach - I'd like to see the "Are you sure?" feature
 which we all know from Windows also in the database. And although we cannot catch the DROP operation to ask
 the "are you sure" question, we can implement a similar approach: The idea is to declare the object to be
 dropped beforehand. So we have a package which holds the declared object and a trigger which looks into
 the package and raises an error message if the object has not been declared. First we create the package.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;replace&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt; PREDROP &lt;span style="color: #804040;"&gt;&lt;b&gt;authid&lt;/b&gt;&lt;/span&gt; current_user &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  g_forsession &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
  g_nextobject &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
  g_objectname &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;''&lt;/span&gt;;
  g_objecttype &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;''&lt;/span&gt;;
  g_objectuser &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;''&lt;/span&gt;;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj(
    p_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;,
    p_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: teal;"&gt;user&lt;/span&gt;,
    p_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TABLE'&lt;/span&gt;
  );
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; sess(
    p_enable &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;
  );
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; clear; 
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; info;
&lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; PREDROP;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
sho err

&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;replace&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;body&lt;/b&gt;&lt;/span&gt; PREDROP &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; sess (
    p_enable &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;
  ) &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt; 
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
     g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_enable;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; sess;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;;

    g_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; obj;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; obj (
    p_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;,
    p_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: teal;"&gt;user&lt;/span&gt;,
    p_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;default&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TABLE'&lt;/span&gt;
  ) &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;true&lt;/span&gt;;
    g_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_objectname;
    g_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_objecttype;
    g_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; p_objectuser;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; obj;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; clear &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;false&lt;/span&gt;;
    g_objectname &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objecttype &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
    g_objectuser &lt;span style="color: #804040;"&gt;&lt;b&gt;:=&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; clear;

  &lt;span style="color: #804040;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; info &lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt;
  &lt;span style="color: #804040;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'********************************************'&lt;/span&gt;);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Enable Session Flag: '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: #804040;"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/span&gt; g_forsession &lt;span style="color: #804040;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TRUE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'FALSE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;));
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Enable Object Flag:  '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: #804040;"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;when&lt;/b&gt;&lt;/span&gt; g_nextobject &lt;span style="color: #804040;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'TRUE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'FALSE'&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;));
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Object name:         '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;g_objectname);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Object type:         '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;g_objecttype);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'* Object owner:        '&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;||&lt;/b&gt;&lt;/span&gt;g_objectuser);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;'********************************************'&lt;/span&gt;);
    dbms_output.put_line(&lt;span style="color: magenta;"&gt;''&lt;/span&gt;);
  &lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; info;
&lt;span style="color: #804040;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt; PREDROP;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
sho err

&lt;span style="color: teal;"&gt;grant&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;execute&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;on&lt;/span&gt; PREDROP &lt;span style="color: teal;"&gt;to&lt;/span&gt; &lt;span style="color: teal;"&gt;public&lt;/span&gt;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;

&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: teal;"&gt;public&lt;/span&gt; &lt;span style="color: teal;"&gt;synonym&lt;/span&gt; PREDROP &lt;span style="color: #804040;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; sys.PREDROP
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Don't forget to grant &lt;b&gt;EXECUTE&lt;/b&gt; Privileges and to create a public synonym in order to make the
 package accessible for everyone. Creating the Trigger is the next step. As said before, it simply
 checks whether the object to be dropped ( &lt;b&gt;ora_dict_obj_name&lt;/b&gt;, &lt;b&gt;ora_dict_obj_type&lt;/b&gt;, &lt;b&gt;ora_dict_obj_owner&lt;/b&gt;) 
 has been declared with the PRECODE package. If not, the trigger raises an error, otherwise it does
 nothing and the operation will succeed.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;&lt;font color="#804040"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; replace &lt;font color="#6a5acd"&gt;trigger&lt;/font&gt; tr_drop_protection 
before &lt;font color="#804040"&gt;&lt;b&gt;drop&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;truncate&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;on&lt;/font&gt; database
declare
  l_raiseerror     &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;

  l_namematch      &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_typematch      &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_usermatch      &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_match          &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  l_always_allowed &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;

  &lt;font color="#0000ff"&gt;/* UPDATE: &lt;/font&gt;
&lt;font color="#0000ff"&gt;   * Some code need to be allowed in general!&lt;/font&gt;
&lt;font color="#0000ff"&gt;   */&lt;/font&gt;
  &lt;font color="#6a5acd"&gt;function&lt;/font&gt; always_allowed(p_owner &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;, p_object &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;) &lt;font color="#6a5acd"&gt;return&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;is&lt;/font&gt;
    l_always &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  &lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; p_owner &lt;font color="#804040"&gt;&lt;b&gt;like&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'APEX_%'&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; p_object &lt;font color="#804040"&gt;&lt;b&gt;like&lt;/b&gt;&lt;/font&gt; &lt;font color="#ff00ff"&gt;'WWV_FLOW_%LOG%'&lt;/font&gt; &lt;font color="#6a5acd"&gt;then&lt;/font&gt;
      l_always := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;
      goto ende;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;
    &amp;lt;&amp;lt;ende&amp;gt;&amp;gt;
    &lt;font color="#6a5acd"&gt;return&lt;/font&gt; l_always;
  &lt;font color="#6a5acd"&gt;end&lt;/font&gt; always_allowed;

  &lt;font color="#6a5acd"&gt;function&lt;/font&gt; match(p_string1 &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;, p_string2 &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/font&gt;) &lt;font color="#6a5acd"&gt;return&lt;/font&gt; &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; &lt;font color="#6a5acd"&gt;is&lt;/font&gt;
    l_match &lt;font color="#2e8b57"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/font&gt; := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
  &lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; p_string1 = p_string2 &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; p_string2 &lt;font color="#6a5acd"&gt;is&lt;/font&gt; &lt;font color="#6a5acd"&gt;null&lt;/font&gt; &lt;font color="#6a5acd"&gt;then&lt;/font&gt; 
      l_match := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;else&lt;/font&gt; 
      l_match := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;return&lt;/font&gt; l_match;
  &lt;font color="#6a5acd"&gt;end&lt;/font&gt; match;
&lt;font color="#6a5acd"&gt;begin&lt;/font&gt;
    l_namematch := match(ora_dict_obj_name, PREDROP.g_objectname);
    l_typematch := match(ora_dict_obj_type, PREDROP.g_objecttype);
    l_usermatch := match(ora_dict_obj_owner, PREDROP.g_objectuser);
    l_match := l_namematch &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; l_usermatch &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; l_typematch;
    l_always_allowed := always_allowed(ora_dict_obj_owner, ora_dict_obj_name);

    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; ((PREDROP.g_nextobject &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; PREDROP.g_forsession) &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; l_match) &lt;font color="#804040"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/font&gt; l_always_allowed  &lt;font color="#6a5acd"&gt;then&lt;/font&gt;
      l_raiseerror := &lt;font color="#6a5acd"&gt;false&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;else&lt;/font&gt;
      l_raiseerror := &lt;font color="#6a5acd"&gt;true&lt;/font&gt;;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;

    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/font&gt; PREDROP.g_forsession &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/font&gt; l_raiseerror &lt;font color="#6a5acd"&gt;then&lt;/font&gt; 
      PREDROP.clear;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;

    &lt;font color="#6a5acd"&gt;if&lt;/font&gt; l_raiseerror &lt;font color="#6a5acd"&gt;then&lt;/font&gt;
      raise_application_error(&lt;font color="#ff00ff"&gt;-20000&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'Enable DROP/TRUNCATE of '&lt;/font&gt;||ora_dict_obj_type|| &lt;font color="#ff00ff"&gt;' &amp;quot;'&lt;/font&gt;||ora_dict_obj_name||&lt;font color="#ff00ff"&gt;'&amp;quot; with the '&lt;/font&gt;||upper(&lt;font color="#ff00ff"&gt;'PREDROP'&lt;/font&gt;)||&lt;font color="#ff00ff"&gt;' package.'&lt;/font&gt;);
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;if&lt;/font&gt;;
&lt;font color="#6a5acd"&gt;end&lt;/font&gt;;
/&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
That's it. From now on, DROP and TRUNCATE operations need to be declared beforehand ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;pre&gt;SQL&amp;gt; drop table emp3;
drop table emp3
*
ERROR in line 1:
ORA-00604: Error at recursive SQL level 1
ORA-20000: Enable DROP/TRUNCATE of TABLE "EMP3" with the PREDROP package.
ORA-06512: line 36

SQL&amp;gt; exec predrop.obj('EMP3');

PL/SQL-Procedure successfully completed.

SQL&amp;gt; drop table emp3;

Table dropped.

SQL&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
This implementation of the PREDROP package already provides some flexibility. Setting
 the object name, type or owner to SQL NULL matches everything. Normally a declaration
 is valid until it has been matched by a DROP operation - after calling PREDROP.SESS it will be
 valid until the end of the session - this is useful when runnung SQL scripts.
 Using regular expressions or LIKE syntax would make the package even more flexible ... but
 this is a story for another blog posting ... 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Tell me what you think!
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-8980919228893107418?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/VojTnFhcFY0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/VojTnFhcFY0/drop-table-sind-sie-sicher.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>1</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1391265 11.5801863</georss:point><georss:box>47.969588 11.2643293 48.308665000000005 11.896043299999999</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/11/drop-table-sind-sie-sicher.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-3339938634803151072</guid><pubDate>Fri, 21 Oct 2011 12:37:00 +0000</pubDate><atom:updated>2011-11-14T09:58:44.718+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">vortrag</category><category domain="http://www.blogger.com/atom/ns#">konferenz</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>Ab morgen: DOAG2011</title><description>&lt;div lang="de"&gt;
Bis zur &lt;a href="http://www.doag.org/de/events/konferenzen/doag-2011.html" target="_blank"&gt;DOAG2011&lt;/a&gt; ist es ja nicht mehr solange hin - ich werde an allen drei Tagen dort sein und freue mich schon darauf, das eine oder andere Gesicht aus der Oracle-Community wiederzusehen ... Wie in den letzten Jahren habe ich auch dieses Jahr wieder ein paar Vorträge - hier sind sie ...
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Demo-Kino: &lt;b&gt;Transformers 4.1: Von Standard nach Cool&lt;/b&gt; &lt;br /&gt; 
15.11.2011 10:00 - 10:45 Uhr - Foyer Tokio&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
Mit nur wenig Aufwand kann man einer APEX-Applikation moderne Elemente hinzufügen. Eine
eher langweilige Geschäftsanwendung wird im Film transformiert - Elemente wie "Google Suggest",
Karten, Volltextsuche und moderne Layoutelemente kommen hinzu. Die neue Anwendung holt den
Nutzer dort ab, wo er steht, mit Anwendungsfeatures, die er aus dem Internet kennt ...
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Das Navi in der Datenbank: Oracle11g has NAVTEQ on Board&lt;/b&gt;&lt;br /&gt; 
16.11.2011 10:00 - 10:45 Uhr - Raum Tokio&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
Wussten Sie schon, dass Sie eine postalische Adresse mit der Oracle-Datenbank mit einer einfachen SQL-Abfrage in Koordinaten, also Längen- und Breitengrade, umwandeln können. Mit der Geocoding-Engine ist das überhaupt kein Problem - und durch die enge Integration mit der Datenbank kann dies Teil der normalen Geschäftslogik werden.
&lt;/div&gt;
&lt;div&gt;
Basis dafür sind NAVTEQ-Daten - Oracle has NAVTEQ on Board. Der Vortrag zeigt, was das NAVTEQ ODF Dataset (Oracle Data Format) beinhaltet, wie man es installiert und wie man damit nicht nur Geocoding, sondern auch Routing oder andere Operationen durchführen kann
(diesen Vortrag mache ich gemeinsam mit Till Kreiler von NAVTEQ).
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SQL oder NoSQL? Das ist hier die Frage! Die "Oracle NoSQL Datenbank"&lt;/b&gt;&lt;br /&gt; 
16.11.2011 14:00 - 14:45 Uhr - Raum Tokio&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;i&gt;Dieses Thema finde ich ziemlich spannend - ein wenig habe ich schon mit der neuen &lt;b&gt;Oracle NoSQL Database&lt;/b&gt; herumgespielt - und ich muss sagen: Das ist wirklich ein neuer Ansatz - und auf die Reaktionen und Diskussionen bin ich auch schon sehr gespannt ...&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Bekannte Webseiten wie Twitter, Facebook oder URL-Verkürzer wie tinyurl.com setzen NoSQL-Datenbanken ein - und auf der OOW wurde jüngst die Oracle NoSQL Database angekündigt. Der Vortrag stellt die Oracle NoSQL Database vor, geht auf Unterschiede zwischen NoSQL-Datenbanken und den "klassischen" RDBMS ein und stellt mögliche Einsatzszenarien vor.

NoSQL-Datenbanken werden genutzt, um extrem große Datenmengen extrem vieler User zu speichern. Im Gegensatz zu unserer "klassischen" Oracle-Datenbank spielen das Datenmodell, Transaktionskonzepte und Datenintegrität keine Rolle - das einzige, was zählt, ist die wirklich ständige Verfügbarkeit, die mit massiver Parallelisierung erreicht wird. Eine NoSQL-Datenbank richtet sich an Entwickler, denn es gibt keine Abfragesprache und keinen Query-Optimizer. Zugriffe erfolgen über eine Programmierschnittstelle (API) - alle Intelligenz steckt in der Anwendung.
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;apex.meinefirma.de: APEX Hosting im eigenen Unternehmen&lt;/b&gt;&lt;br /&gt; 
17.11.2011 13:00 - 13:45 Uhr - Raum Istabul&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
Nahezu überall ändern sich Prozesse und Anforderungen immer schneller: gebraucht wird also eine Plattform, welche die Entwicklung neuer Anwendungen genauso schnell ermöglicht.
Der öffentliche Demoserver "apex.oracle.com" zeigt, wie es geht: Entwickler können Ihre Workspaces selbstständig beantragen und verwalten, ohne manuelles des DBA Eingreifen sofort aktiv werden; neue Anwendungen stehen sofort bereit.
Der Vortrag zeigt, wie ein Server "apex.meinefirma.de" aufgesetzt und betrieben werden kann, welche Hardware man braucht, wie Ressourcenkonflikte gelöst werden und worauf geachtet werden sollte. 
Das ist Cloud Computing "in Action".
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Auf der ODTUG Kscope-Konferenz, an der ich im Juni teilgenommen hatte, wurde Twitter ganz massiv genutzt - Tweets über die einzelnen Vorträge und neue Ideen kamen quasi im Sekundentakt. Ich bin gespannt, wie das auf der DOAG2011 läuft. Meine Teamkollegen und ich werden euch über den Twitter
 Account &lt;a href="http://www.twitter.com/oraclebudb" target="_blank"&gt;@OracleBUDB&lt;/a&gt; und natürlich mit
 dem Hashtag &lt;a href="http://twitter.com/#%21/search/%23doag2011" target="_blank"&gt;#doag2011&lt;/a&gt; auf dem
 Laufenden halten ... also dranbleiben ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
This is a posting about the DOAg2011 conference and therefore in german only.
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-3339938634803151072?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/Tst8X_-Ug1U" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/Tst8X_-Ug1U/noch-etwas-mehr-als-drei-wochen.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><georss:featurename>Nürnberg, Deutschland</georss:featurename><georss:point>49.45052 11.08048</georss:point><georss:box>49.285357499999996 10.764623 49.6156825 11.396336999999999</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/10/noch-etwas-mehr-als-drei-wochen.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-6676452663001950262</guid><pubDate>Tue, 04 Oct 2011 07:39:00 +0000</pubDate><atom:updated>2011-10-04T14:34:29.166+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">plsql</category><category domain="http://www.blogger.com/atom/ns#">array</category><category domain="http://www.blogger.com/atom/ns#">STRUCT</category><category domain="http://www.blogger.com/atom/ns#">objects</category><category domain="http://www.blogger.com/atom/ns#">jvm</category><title>Von Java nach SQL: Java-Objekte und die Datenbank-JVM</title><description>&lt;div lang="en" style="color: #cc6600; display: none;"&gt;
From Java to SQL: Java objects and the database JVM&lt;/div&gt;
&lt;div lang="de"&gt;
In der Vergangenheit hatte ich ja schon einige Blog-Postings zum Thema "Java in der Datenbank";
 das letzte Posting &lt;a href="http://sql-plsql-de.blogspot.com/2011/09/twitter-postings-mit-der-datenbank-sql.html" target="_blank"&gt;zum Thema Twitter-Postings mit der Datenbank&lt;/a&gt;, die diversen Postings zum
 Thema &lt;a href="http://plsqlexecoscomm.sourceforge.net/" target="_blank"&gt;Dateisystem-Zugriffe&lt;/a&gt; haben
 alle eines gemein: Sie verwenden die in der Datenbank enthaltene Java-Engine. Wenn es aber darum
 geht, Java-Funktionen aus PL/SQL oder SQL heraus zu nutzen, ist &lt;i&gt;immer&lt;/i&gt; auch eine Parameter-Mapping
 gefragt. Und genau dem möchte ich mich heute widmen. Dabei geht es mir aber nicht um das Abbilden
 eines VARCHAR2, NUMBER oder DATE auf Java-Datentypen - das ist sehr einfach, wie man hier sehen kann ...
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: #804040;"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/span&gt; compile java source named simple_test &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;

&lt;span style="color: slateblue;"&gt;public&lt;/span&gt; class SimpleTest {
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static String getString() {
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: magenta;"&gt;"Hallo Welt"&lt;/span&gt;;
  }
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static java.sql.Timestamp getDate() {
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; new java.sql.Timestamp(new java.util.&lt;span style="color: seagreen;"&gt;&lt;b&gt;Date&lt;/b&gt;&lt;/span&gt;().getTime());
  }
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static int getNumber() {
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: magenta;"&gt;4711&lt;/span&gt;;
  }
} 
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace package simple_test_plsql &lt;span style="color: slateblue;"&gt;is&lt;/span&gt;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_string &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_date &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;date&lt;/b&gt;&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_number &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/span&gt;;
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt; simple_test_plsql;
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace package body simple_test_plsql &lt;span style="color: slateblue;"&gt;is&lt;/span&gt;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_string &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; 
  language java name &lt;span style="color: magenta;"&gt;'SimpleTest.getString() return java.lang.String'&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_date &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;date&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;
  language java name &lt;span style="color: magenta;"&gt;'SimpleTest.getDate() return java.sql.Timestamp'&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_number &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;
  language java name &lt;span style="color: magenta;"&gt;'SimpleTest.getNumber() return int'&lt;/span&gt;;
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt; simple_test_plsql;
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  simple_test_plsql.get_string,
  simple_test_plsql.get_date,
  simple_test_plsql.get_number
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; dual
/

GET_STRING           GET_DATE            GET_NUMBER
-------------------- ------------------- ----------
Hallo Welt           21.09.2011 09:19:40       4711
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Den Experten ist sicher schon aufgefallen, dass die Java-Methoden alle "static" sind; das
 ist auch logisch so, denn PL/SQL ist ja keine objektorientierte Sprache. Mit "statischen" Java-Methoden
 wird Java wie eine prozedurale Sprache genutzt - es entspricht eher dem Konzept von PL/SQL, daher
 können nur statische Java-Methoden auf PL/SQL-Pakete, Prozeduren oder Funktionen abgebildet werden.
&lt;/div&gt;
&lt;div lang="de"&gt;
Das einzige, wo man ein wenig aufpassen muss, sind DATE-Mappings - diese können auf
 die Klassen java.sql.Date und java.sql.Timestamp abgebildet werden. In Java bedeutet das
 aber etwas anderes als in SQL. Arbeitet man beim Mapping mit &lt;b&gt;java.sql.Date&lt;/b&gt;, dann
 werden nur Tag, Monat und Jahr an die SQL-Ebene zurückgegeben - also
 das Datum - möchte man die Uhrzeit haben, sollte man mit &lt;b&gt;java.sql.Timestamp&lt;/b&gt; 
 arbeiten.
 Aber abgesehen davon ist das Mapping solcher Datentypen ja wirklich einfach - und wenn
 man Java-Bibliotheken in der Datenbank verwendet, sollte man sich am besten stets 
 eine eigene "Schicht" mit Java-Methoden schreiben, die einfach auf SQL und PL/SQL
 abzubilden sind - wo die Methodensignaturen also am besten nur solche einfachen
 Datentypen nutzen und keine komplexen Objekte. 
&lt;/div&gt;
&lt;div lang="de"&gt;
Aber jetzt geht's ans Eingemachte: Angenommen, wir haben eine Java-Bibliothek (und als Beispiel 
 nehmen wir mal &lt;a href="http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html" target="_blank"&gt;java.io.File&lt;/a&gt;), die ein komplexes Objekt repräsentiert. Und wir möchten nun eben &lt;i&gt;nicht&lt;/i&gt; für jedes
 Attribut einen eigenen Call bauen, sondern alle relevanten Attribute mit &lt;i&gt;einem einzigen&lt;/i&gt; Call
 abholen. Uns prinzipiell gibt es in der Datenbank ja auch Objekttypen bzw. &lt;i&gt;User Defined Types&lt;/i&gt;,
 mit denen man sowas wie ein "File" modellieren kann. Also fangen wir mal damit an.
&lt;pre&gt;
&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;type&lt;/span&gt; file_t &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; object(
  file_path      &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;),
  file_name      &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;),
  file_size      &lt;span style="color: seagreen;"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/span&gt;,
  last_modified  &lt;span style="color: seagreen;"&gt;&lt;b&gt;date&lt;/b&gt;&lt;/span&gt;,
  is_dir         &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;),
  is_writeable   &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;),
  is_readable    &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;),
  file_exists    &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)
)
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Allerdings kann man nun keine direkte Verbindung zwischen dem SQL-Typen &lt;b&gt;FILE_T&lt;/b&gt; und
 der Java-Klasse &lt;b&gt;java.io.File&lt;/b&gt; herstellen - beide haben ja überhaupt nichts miteinander
 zu tun - ein Mapping ist aber mit Hilfe von einer "Java-Brückenklasse" möglich: Mit 
 &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/STRUCT.html" target="_blank"&gt;oracle.sql.STRUCT&lt;/a&gt; kann man Objekttypen aus Java heraus erstellen und an SQL bzw. PL/SQL
 zurückgeben. Was wir also brauchen, ist eine (statische) Java-Methode, die mit Hilfe von 
 &lt;b&gt;java.io.File&lt;/b&gt; die Information zu einer Datei holt, damit ein &lt;b&gt;STRUCT&lt;/b&gt; für den &lt;b&gt;FILE_T&lt;/b&gt; erzeugt und
 diese kann dann in die SQL-Ebene zurückgibt.
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: #804040;"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/span&gt; compile java source named java_file &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;
import java.math.*;
import java.util.*;
import java.io.*;

import java.sql.*;

import oracle.sql.*;
import oracle.jdbc.*;

&lt;span style="color: slateblue;"&gt;public&lt;/span&gt; class JavaFile {
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static STRUCT getFile(String pFile) throws &lt;span style="color: slateblue;"&gt;Exception&lt;/span&gt; {
    Connection       con    = DriverManager.getConnection(&lt;span style="color: magenta;"&gt;"jdbc:default:connection:"&lt;/span&gt;);
    StructDescriptor sDescr = StructDescriptor.createDescriptor(&lt;span style="color: magenta;"&gt;"FILE_T"&lt;/span&gt;, con);
    Object[]         o      = new Object[&lt;span style="color: magenta;"&gt;8&lt;/span&gt;];

    &lt;span style="color: slateblue;"&gt;File&lt;/span&gt; f = new &lt;span style="color: slateblue;"&gt;File&lt;/span&gt;(pFile);
    &lt;span style="color: slateblue;"&gt;if&lt;/span&gt; (f.&lt;span style="color: #804040;"&gt;&lt;b&gt;exists&lt;/b&gt;&lt;/span&gt;()) {
     o[&lt;span style="color: magenta;"&gt;0&lt;/span&gt;] = f.getPath();
     o[&lt;span style="color: magenta;"&gt;1&lt;/span&gt;] = f.getName();
     o[&lt;span style="color: magenta;"&gt;2&lt;/span&gt;] = new BigDecimal(f.length());
     o[&lt;span style="color: magenta;"&gt;3&lt;/span&gt;] = new java.sql.Timestamp(f.lastModified());
     o[&lt;span style="color: magenta;"&gt;4&lt;/span&gt;] = (f.isDirectory()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;5&lt;/span&gt;] = (f.canWrite()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;6&lt;/span&gt;] = (f.canRead()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;7&lt;/span&gt;] = &lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;;
     &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; new STRUCT(sDescr, con, o);
    } &lt;span style="color: slateblue;"&gt;else&lt;/span&gt; {
     &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: slateblue;"&gt;null&lt;/span&gt;;
    } 
  }
}
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_file_atts (p_file &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;) &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; file_t
&lt;span style="color: slateblue;"&gt;is&lt;/span&gt; language java name &lt;span style="color: magenta;"&gt;'JavaFile.getFile(java.lang.String) return oracle.sql.STRUCT'&lt;/span&gt;;
/
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Hier muss der Java-Code mit der SQL-Ebene zusammenspielen - deshalb wird zuerst eine
 JDBC-"Verbindung" aufgebaut - das ist aber nichts weiter als eine Art "Pointer" auf
 die Datenbanksitzung, denn das Java läuft ja bereits in der Datenbank. Es wird 
 ein &lt;b&gt;&lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/StructDescriptor.html" target="_blank"&gt;StructDescriptor&lt;/a&gt;&lt;/b&gt;-Objekt erzeugt, welches auf den vorher erzeugten Typen &lt;b&gt;FILE_T&lt;/b&gt; 
 zeigt. Alle Attribute des &lt;b&gt;FILE_T&lt;/b&gt; werden auf Java-Seite in einem Array der Klasse &lt;b&gt;Object[]&lt;/b&gt; 
 abgelegt. Hier muss man als Entwickler aufpassen, dass die verwendeten Java-Typen auf
 die Datentypen des SQL-Typen passen (siehe einfache Mappings oben). Mit diesem Array, 
 dem StructDescriptor-Objekt und dem Connection-Objekt wird dann
 ganz zum Schluß ein &lt;b&gt;STRUCT&lt;/b&gt;-Objekt generiert, welches genau auf den Typen &lt;b&gt;FILE_T&lt;/b&gt; passt. 
 Natürlich kann man auch komplexere Dinge bauen und ein "STRUCT in ein STRUCT" schachteln, man
 muss nur aufpassen, dass alles zur Definition der Objekttypen in SQL passt.
&lt;/div&gt;
&lt;div lang="de"&gt;
Zum Abschluß kommt wieder die PL/SQL-Definition der Funktion - in PL/SQL wird
 als IN Parameter ein &lt;b&gt;VARCHAR2&lt;/b&gt; und als Rückgabewert ein &lt;b&gt;FILE_T&lt;/b&gt; deklariert. Folgerichtig
 passt das auf ein &lt;b&gt;java.lang.String&lt;/b&gt; als Eingabe- und ein &lt;b&gt;oracle.sql.STRUCT&lt;/b&gt; als 
 Rückgabewert. Alle Objekttypen werden auf Java-Seite als &lt;b&gt;oracle.sql.STRUCT&lt;/b&gt; abgebildet - die
 Verknüpfung mit dem konkreten Objekttypen erledigt der &lt;b&gt;StructDescriptor&lt;/b&gt; ...
&lt;/div&gt;
&lt;div lang="de"&gt;
Alles klar? Dann können wir testen ...
&lt;br /&gt;
&lt;pre&gt;SQL&amp;gt; select get_file_atts('/') from dual;
select get_file_atts('/') from dual
                               *
FEHLER in Zeile 1:
ORA-29532: Java-Aufruf durch nicht abgefangene Java-Exception beendet:
java.security.AccessControlException: the Permission (java.io.FilePermission /
read) has not been granted to SCOTT. The PL/SQL to grant this is
dbms_java.grant_permission( 'SCOTT', 'SYS:java.io.FilePermission', '/', 'read'
)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Ach ja: Zum Dateisystemzugriff braucht es Privilegien - die muss der DBA einräumen. Wenn
 Ihr vor diesen Meldungen Ruhe haben wollt, gebt eurem Datenbankschema das &lt;b&gt;JAVASYSPRIV&lt;/b&gt;-Privileg,
 dann har er alle Rechte, die man haben kann (für Produktion nicht zu empfehlen). Alternativ könnt Ihr einfach den in der
 Fehlermeldung dargestellten Aufruf ausführen - der räumt genau das fehlende Privileg ein. Wenn Ihr
 das Privileg habt, probiert es nochmal ...
&lt;br /&gt;
&lt;pre&gt;SQL&amp;gt; select get_file_atts('/tmp') from dual;

GET_FILE_ATTS('/TMP')(FILE_PATH, FILE_NAME, FILE_SIZE, LAST_MODIFIED, IS_DIR, IS
--------------------------------------------------------------------------------
FILE_T('/tmp', 'tmp', 126976, '21.09.2011 10:25:22', 'Y', 'Y', 'Y', 'Y')

1 Zeile wurde ausgewählt.
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
So weit so gut. Wir haben es also geschafft, ein strukturiertes Objekt von Java nach
 PL/SQL zu übertragen. Analog dazu kann man nun für alle Objekte vorgehen:
 &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;SQL-Objekttypen erzeugen&lt;/li&gt;
&lt;li&gt;Java Methode erzeugen, die das eigentliche Java-Objekt auf eine STRUCT-Instanz abbildet, dabei
      mit dem StructDescriptor und dem Object[]-Array arbeiten&lt;/li&gt;
&lt;li&gt;STRUCT-Instanz aus Java zurückgeben und in SQL übernehmen&lt;/li&gt;
&lt;li&gt;PL/SQL Wrapper für die neue Java Stored Procedure erstellen&lt;/li&gt;
&lt;/ul&gt;
Bleibt die nächste (und im Datenbankumfeld spannende) Aufgabe: Ich möchte 
 ein Directory-Listing abbilden, also eine ganze Reihe von strukturierten Objekten
 zurückgeben. Im reinen PL/SQL geht haben wir hierfür die &lt;i&gt;Table Functions&lt;/i&gt; 
 - und ein ähnliches Konzept nutzen wir auch in Java. Zunächst brauchen wir,
 wie bei der PL/SQL Table Function, einen Objekttypen, der die Dateiliste repräsentiert - das ist einfach:
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;type&lt;/span&gt; file_ct &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; &lt;span style="color: slateblue;"&gt;table&lt;/span&gt; &lt;span style="color: slateblue;"&gt;of&lt;/span&gt; file_t
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Und wieder gilt es, aus Java heraus eine Instanz dieses Typs &lt;b&gt;FILE_CT&lt;/b&gt; zu erzeugen. Für Varray- oder
 Table Types gibt es jedoch eine andere Java-"Brückenklasse": &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/ARRAY.html" target="_blank"&gt;oracle.sql.ARRAY&lt;/a&gt;. Der Umgang damit
 ist aber ganz ähnlich wie bei der Klasse oracle.sql.STRUCT. Es wird ein &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/ArrayDescriptor.html" target="_blank"&gt;ArrayDescriptor&lt;/a&gt;-Objekt benötigt, der die 
 Verbindung zum konkreten SQL-Typen herstellt, und mit diesem, dem Connection-Objekt und einem
 Standard-Java-Array wird die Instanz vom Typ &lt;b&gt;oracle.sql.ARRAY&lt;/b&gt; erzeugt, die genau auf den &lt;b&gt;FILE_CT&lt;/b&gt; 
 passt. Das ganze als Code ...
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;public&lt;/span&gt; class JavaFile {
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static ARRAY getFileList(String pFile) throws &lt;span style="color: slateblue;"&gt;Exception&lt;/span&gt; {
    Connection       con    = DriverManager.getConnection(&lt;span style="color: magenta;"&gt;"jdbc:default:connection:"&lt;/span&gt;);
    StructDescriptor sDescr = StructDescriptor.createDescriptor(&lt;span style="color: magenta;"&gt;"FILE_T"&lt;/span&gt;, con);
    ArrayDescriptor  aDescr = ArrayDescriptor.createDescriptor(&lt;span style="color: magenta;"&gt;"FILE_CT"&lt;/span&gt;, con);
    Object[]         o      = new Object[&lt;span style="color: magenta;"&gt;8&lt;/span&gt;];

    &lt;span style="color: blue;"&gt;/* Array containing java File objects */&lt;/span&gt;
    &lt;span style="color: slateblue;"&gt;File&lt;/span&gt;[]   f = new &lt;span style="color: slateblue;"&gt;File&lt;/span&gt;(pFile).listFiles();

    &lt;span style="color: blue;"&gt;/* Array containing SQL STRUCT objects */&lt;/span&gt;
    STRUCT[] a = new STRUCT[f.length];

    &lt;span style="color: blue;"&gt;/* now loop through the File array and create a STRUCT instance for each file */&lt;/span&gt;
    &lt;span style="color: slateblue;"&gt;for&lt;/span&gt; (int i=&lt;span style="color: magenta;"&gt;0&lt;/span&gt;;i&amp;lt;f.length;i++) {
     o[&lt;span style="color: magenta;"&gt;0&lt;/span&gt;] = f[i].getPath();
     o[&lt;span style="color: magenta;"&gt;1&lt;/span&gt;] = f[i].getName();
     o[&lt;span style="color: magenta;"&gt;2&lt;/span&gt;] = new BigDecimal(f[i].length());
     o[&lt;span style="color: magenta;"&gt;3&lt;/span&gt;] = new java.sql.Timestamp(f[i].lastModified());
     o[&lt;span style="color: magenta;"&gt;4&lt;/span&gt;] = (f[i].isDirectory()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;5&lt;/span&gt;] = (f[i].canWrite()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;6&lt;/span&gt;] = (f[i].canRead()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;7&lt;/span&gt;] = &lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;
     a[i] = new STRUCT(sDescr, con, o);
    } 
    &lt;span style="color: blue;"&gt;/* Create and return the ARRAY object which maps to the SQL type */&lt;/span&gt;
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; new ARRAY(aDescr, con, a);
  }
}
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_file_list (p_file &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;) &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; file_ct
&lt;span style="color: slateblue;"&gt;is&lt;/span&gt; language java name &lt;span style="color: magenta;"&gt;'JavaFile.getFileList(java.lang.String) return oracle.sql.ARRAY'&lt;/span&gt;;
/
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Und das ist im Grunde genommen nur eine Erweiterung obigen Codes. Durch die Liste der File-Objekte,
 die von &lt;a href="http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#listFiles%28%29" target="_blank"&gt;java.io.File.listFiles()&lt;/a&gt; zurückgegeben wird, laufen wir in einer Schleife durch,
 erzeugen für jedes File-Objekt eine &lt;b&gt;STRUCT&lt;/b&gt;-Instanz und packen auch diese in ein Array. Das
 wird dann mit dem &lt;b&gt;ArrayDescriptor&lt;/b&gt; auf den SQL-Typen &lt;b&gt;FILE_CT&lt;/b&gt; abgebildet und als &lt;b&gt;oracle.sql.ARRAY&lt;/b&gt;-Objekt
 zurückgegeben. Fertig - Test.
&lt;br /&gt;
&lt;pre&gt;SQL&amp;gt; select file_name, last_modified, file_size from table(get_file_list('/'))

FILE_NAME                 LAST_MODIFIED        FILE_SIZE
------------------------- ------------------- ----------
wget-log                  27.04.2011 16:24:02        496
boot                      02.02.2011 13:22:58       1024
misc                      25.07.2011 09:29:09          0
stage                     04.04.2011 11:27:57          7
lib                       15.07.2011 11:06:27       4096
etc                       25.07.2011 09:29:07       4096
root                      15.07.2011 11:14:01       4096
bin                       02.02.2011 13:28:45       4096
:                         :                            :
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Eigentlich ganz einfach, oder? Mit dem hier vorgestellten lässt sich nun jede beliebige
 Java-Bibliothek in der Datenbank nutzen - die einzige Voraussetzung ist, dass sie keinen
 Native-Code verwendet - nur 100%-Java-Bibliotheken laufen in der Datenbank. Zum Ansprechen
 aus SQL und PL/SQL überlegt man sich dann eine vernünftige Schnittstelle, erzeugt die
 passenden Java-Klassen, die entweder einfache Datentypen (String, Date, numerische)
 oder komplexe Datentypen als STRUCT oder ARRAY zurückgeben. Diese werden dann auf SQL-Ebene
 durch PL/SQL-Packages und Objekttypen repräsentiert. Die Code-Packages zum
 &lt;a href="http://plsqlexecoscomm.sourceforge.net/" target="_blank"&gt;Dateisystem-Zugriff&lt;/a&gt;,
 zum &lt;a href="http://plsqlmailclient.sourceforge.net/" target="_blank"&gt;Umgang mit einem POP3- oder IMAP-Mailserver&lt;/a&gt; oder zum &lt;a href="http://sql-plsql-de.blogspot.com/2010/11/zip-archive-einpacken-und-auspacken-das.html" target="_blank"&gt;Ein- und Auspacken von ZIP-Archiven&lt;/a&gt; arbeiten alle genau so - 
 und wie gesagt: Jede andere Java-Bibliothek lässt sich genauso 
 einbinden. Damit gibt es keine Grenzen in der Oracle-Datenbank. 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
In the past I had quite a number of postinhs in which I made use of the Java engine within the Oracle
 Database. Examples are the previous posting 
 &lt;a href="http://sql-plsql-de.blogspot.com/2011/09/twitter-postings-mit-der-datenbank-sql.html" target="_blank"&gt;about automated tweets from PL/SQL&lt;/a&gt; (which was about using "twitter4j" in the database) or the
 postings about 
 &lt;a href="http://plsqlexecoscomm.sourceforge.net/" target="_blank"&gt;File- and operating system access&lt;/a&gt;.
 Today I'd like to elaborate a bit about a fundamental thing which one has to accomplish when
 using Java in the database: The parameter mapping. This posting is about how to map input or
 return paramaters in a java method to SQL and PL/SQL types in a package. And the focus will not
 be on the simple mapping of VARCHAR2, NUMBER or DATE datatypes ... these are rather simple, 
 as we can see with this code example ...
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: #804040;"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/span&gt; compile java source named simple_test &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;

&lt;span style="color: slateblue;"&gt;public&lt;/span&gt; class SimpleTest {
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static String getString() {
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: magenta;"&gt;"Hello World"&lt;/span&gt;;
  }
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static java.sql.Timestamp getDate() {
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; new java.sql.Timestamp(new java.util.&lt;span style="color: seagreen;"&gt;&lt;b&gt;Date&lt;/b&gt;&lt;/span&gt;().getTime());
  }
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static int getNumber() {
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: magenta;"&gt;4711&lt;/span&gt;;
  }
} 
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace package simple_test_plsql &lt;span style="color: slateblue;"&gt;is&lt;/span&gt;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_string &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_date &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;date&lt;/b&gt;&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_number &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/span&gt;;
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt; simple_test_plsql;
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace package body simple_test_plsql &lt;span style="color: slateblue;"&gt;is&lt;/span&gt;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_string &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; 
  language java name &lt;span style="color: magenta;"&gt;'SimpleTest.getString() return java.lang.String'&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_date &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;date&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;
  language java name &lt;span style="color: magenta;"&gt;'SimpleTest.getDate() return java.sql.Timestamp'&lt;/span&gt;;
  &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_number &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;
  language java name &lt;span style="color: magenta;"&gt;'SimpleTest.getNumber() return int'&lt;/span&gt;;
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt; simple_test_plsql;
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/span&gt; 
  simple_test_plsql.get_string,
  simple_test_plsql.get_date,
  simple_test_plsql.get_number
&lt;span style="color: slateblue;"&gt;from&lt;/span&gt; dual
/

GET_STRING           GET_DATE            GET_NUMBER
-------------------- ------------------- ----------
Hello World          21.09.2011 09:19:40       4711
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
The "experts" might have notices that all java methods are "static" - that's evident. PL/SQL 
 is a procedural, not an object-oriented language - so when we want to integrate PL/SQL with
 Java in the database we need to use the "procedural part" of Java which are static class methods.
 If you want to map java methods to procedures and functions in a PL/SQL package you must use
 static methods for that.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
When mapping DATE values from Java to PL/SQL a bit attention is needed. Basically
 a date can be represented in java using &lt;b&gt;java.sql.Date&lt;/b&gt; or &lt;b&gt;java.sql.Timestamp&lt;/b&gt;. When
 those are being mapped to &lt;b&gt;DATE&lt;/b&gt; in SQL or PL/SQL, the &lt;b&gt;java.sql.Date&lt;/b&gt; class only
 maps Day, Month and Year - the time in the DATE would be set to midnight. For having the time 
 component also you need to use &lt;b&gt;java.sql.Timestamp&lt;/b&gt;. Apart from this the mapping
 of simple scalar datatypes from Java to SQL and PL/SQL is quite simple. So the first rule
 is to use simple types whenever possible. Complex objects should only be used when they're
 really needed ... because, as we will see, they require additional coding ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
And now we'll handle these: Let's assume we have a Java library doing some stuff and for
 this example we use the &lt;a href="http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html" target="_blank"&gt;java.io.File&lt;/a&gt; class (which is part of standard Java). We'd like to access file
 attributes with SQL functions and we &lt;i&gt;don't want to&lt;/i&gt; have a single call for each
 attribute. We need a SQL function &lt;i&gt;which collects all attributes in one call&lt;/i&gt; - so we need
 a datatype containing all these attributes at the SQL side. We have &lt;i&gt;Object types&lt;/i&gt; (or &lt;i&gt;User-Defined-Types&lt;/i&gt;)
 for that purpose so the first thing we want to do is to create an object type representing 
 a file.
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;type&lt;/span&gt; file_t &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; object(
  file_path      &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;),
  file_name      &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;4000&lt;/span&gt;),
  file_size      &lt;span style="color: seagreen;"&gt;&lt;b&gt;number&lt;/b&gt;&lt;/span&gt;,
  last_modified  &lt;span style="color: seagreen;"&gt;&lt;b&gt;date&lt;/b&gt;&lt;/span&gt;,
  is_dir         &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;),
  is_writeable   &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;),
  is_readable    &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;),
  file_exists    &lt;span style="color: seagreen;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)
)
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
So far we have a Java representation for a file: java.io.File - and we have a SQL representation
 for a file: Our new &lt;b&gt;FILE_T&lt;/b&gt;. But there is absolutly no connection between those. Of course, we
 cannot map the &lt;b&gt;java.io.File&lt;/b&gt; class to our &lt;b&gt;FILE_T&lt;/b&gt; type - the database has no clue how to map
 the attributes. We need to build a "bridge" 
 between &lt;b&gt;java.io.File&lt;/b&gt; and &lt;b&gt;FILE_T&lt;/b&gt;. And this bridge is a special java class:  &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/STRUCT.html" target="_blank"&gt;oracle.sql.STRUCT&lt;/a&gt;.
 So we now need to implement a static Java method (we can only use static methods) which
 uses &lt;b&gt;java.io.File&lt;/b&gt; to collect file attributes and builds a &lt;b&gt;oracle.sql.STRUCT&lt;/b&gt; instance which can
 be mapped to &lt;b&gt;FILE_T&lt;/b&gt;. This code goes here ...
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: #804040;"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/span&gt; compile java source named java_file &lt;span style="color: slateblue;"&gt;as&lt;/span&gt;
import java.math.*;
import java.util.*;
import java.io.*;

import java.sql.*;

import oracle.sql.*;
import oracle.jdbc.*;

&lt;span style="color: slateblue;"&gt;public&lt;/span&gt; class JavaFile {
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static STRUCT getFile(String pFile) throws &lt;span style="color: slateblue;"&gt;Exception&lt;/span&gt; {
    Connection       con    = DriverManager.getConnection(&lt;span style="color: magenta;"&gt;"jdbc:default:connection:"&lt;/span&gt;);
    StructDescriptor sDescr = StructDescriptor.createDescriptor(&lt;span style="color: magenta;"&gt;"FILE_T"&lt;/span&gt;, con);
    Object[]         o      = new Object[&lt;span style="color: magenta;"&gt;8&lt;/span&gt;];

    &lt;span style="color: slateblue;"&gt;File&lt;/span&gt; f = new &lt;span style="color: slateblue;"&gt;File&lt;/span&gt;(pFile);
    &lt;span style="color: slateblue;"&gt;if&lt;/span&gt; (f.&lt;span style="color: #804040;"&gt;&lt;b&gt;exists&lt;/b&gt;&lt;/span&gt;()) {
     o[&lt;span style="color: magenta;"&gt;0&lt;/span&gt;] = f.getPath();
     o[&lt;span style="color: magenta;"&gt;1&lt;/span&gt;] = f.getName();
     o[&lt;span style="color: magenta;"&gt;2&lt;/span&gt;] = new BigDecimal(f.length());
     o[&lt;span style="color: magenta;"&gt;3&lt;/span&gt;] = new java.sql.Timestamp(f.lastModified());
     o[&lt;span style="color: magenta;"&gt;4&lt;/span&gt;] = (f.isDirectory()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;5&lt;/span&gt;] = (f.canWrite()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;6&lt;/span&gt;] = (f.canRead()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;7&lt;/span&gt;] = &lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;;
     &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; new STRUCT(sDescr, con, o);
    } &lt;span style="color: slateblue;"&gt;else&lt;/span&gt; {
     &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; &lt;span style="color: slateblue;"&gt;null&lt;/span&gt;;
    } 
  }
}
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_file_atts (p_file &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;) &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; file_t
&lt;span style="color: slateblue;"&gt;is&lt;/span&gt; language java name &lt;span style="color: magenta;"&gt;'JavaFile.getFile(java.lang.String) return oracle.sql.STRUCT'&lt;/span&gt;;
/
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
The Java engine within the database needs to interact with the SQL layer - we need
 a JDBC database connection for that. This connection is not more than kind of a pointer
 to the actual database session in which the java code runs in. The 
 &lt;b&gt;&lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/StructDescriptor.html" target="_blank"&gt;StructDescriptor&lt;/a&gt;&lt;/b&gt; class is a utility which helps us to create a &lt;b&gt;STRUCT&lt;/b&gt; object
 exactly matching &lt;b&gt;FILE_T&lt;/b&gt;. Note the usage of the connection object and "&lt;b&gt;FILE_T&lt;/b&gt;" when the 
 &lt;b&gt;StructDescriptor&lt;/b&gt; instance is being created. After that we collect all relevant file
 attributes in an Array of the fundamental Java class &lt;b&gt;Object[]&lt;/b&gt;. The developer needs to take
 care about the order within that array: Our object type has eight simple, scalar attributes. The
 Java types in the &lt;b&gt;Object&lt;/b&gt; array (String, int, java.sql.Date) must match the attributes of the object type (VARCHAR, NUMBER, DATE).
 With this array, the &lt;b&gt;StructDescriptor&lt;/b&gt; instance, and the database connection the &lt;b&gt;STRUCT&lt;/b&gt; instance
 is being created and returned in the last step of the program. This &lt;b&gt;STRUCT&lt;/b&gt; instance exactly 
 matches the &lt;b&gt;FILE_T&lt;/b&gt; definition in the SQL layer.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
The final step as (as always) the PL/SQL Wrapper for the static method. We create a 
 function which takes a &lt;b&gt;VARCHAR2&lt;/b&gt; (containing the file path) and returns a &lt;b&gt;FILE_T&lt;/b&gt;. These
 are being mapped to &lt;b&gt;java.lang.String&lt;/b&gt; and &lt;b&gt;oracle.sql.STRUCT&lt;/b&gt; . All object types are being
 encoded as &lt;b&gt;oracle.sql.STRUCT&lt;/b&gt; - the &lt;b&gt;StructDescriptor&lt;/b&gt; objects cares for the mapping to
 the correct SQL type.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Got it ...?  Then try it!
&lt;br /&gt;
&lt;pre&gt;SQL&amp;gt; select get_file_atts('/') from dual;
select get_file_atts('/') from dual
                               *
FEHLER in Zeile 1:
ORA-29532: Java-Aufruf durch nicht abgefangene Java-Exception beendet:
java.security.AccessControlException: the Permission (java.io.FilePermission /
read) has not been granted to SCOTT. The PL/SQL to grant this is
dbms_java.grant_permission( 'SCOTT', 'SYS:java.io.FilePermission', '/', 'read'
)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Ah, yes: You need Java privileges in order to access the file system with a
 Java stored porcedure. In the developing stage you might grant yourself the &lt;b&gt;JAVASYSPRIV&lt;/b&gt; 
 privilege - you will be a "Java superuser" then - on production systems this is not recommended
 you might grant individual privileges there. The practical bit is that Oracle not only throws
 the error message - it also gives the complete PL/SQL call to grant the required permission. So when you have the
 privilege, try again ...
&lt;br /&gt;
&lt;pre&gt;SQL&amp;gt; select get_file_atts('/tmp') from dual;

GET_FILE_ATTS('/TMP')(FILE_PATH, FILE_NAME, FILE_SIZE, LAST_MODIFIED, IS_DIR, IS
--------------------------------------------------------------------------------
FILE_T('/tmp', 'tmp', 126976, '21.09.2011 10:25:22', 'Y', 'Y', 'Y', 'Y')

1 row selected.
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
So far - so good. We managed to create a structured object in java and pass it to
 PL/SQL. You can use this approach for any kind of structured object - and yes: You 
 can nest one &lt;b&gt;oracle.sql.STRUCT&lt;/b&gt; within another &lt;b&gt;oracle.sql.STRUCT&lt;/b&gt; - just as you
 can nest object types in each other. The basic steps are:
 &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Create the SQL object types&lt;/li&gt;
&lt;li&gt;Create the static Java method which creates the STRUCT instance matching the object type using
      the Object[] array and the StructDescriptor class.&lt;/li&gt;
&lt;li&gt;Return the STRUCT instance from java to SQL and PL/SQL&lt;/li&gt;
&lt;li&gt;Create the PL/SQL wrapper for your Java stored procedure&lt;/li&gt;
&lt;/ul&gt;
Then we'll move on to the next (and more interesting) level: We want to pass
 not only a structured object but a list of structured objects from Java to PL/SQL.
 In the PL/SQL world we have &lt;i&gt;Table Functions&lt;/i&gt; for that purpose - and as with these
 we now first create another object type representing our list of files ...
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: slateblue;"&gt;type&lt;/span&gt; file_ct &lt;span style="color: slateblue;"&gt;as&lt;/span&gt; &lt;span style="color: slateblue;"&gt;table&lt;/span&gt; &lt;span style="color: slateblue;"&gt;of&lt;/span&gt; file_t
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
And again: We now need to create an object within Java which maps to this &lt;b&gt;FILE_CT&lt;/b&gt; type.
 But for Varray or table types there is another "Bridging class": &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/ARRAY.html" target="_blank"&gt;oracle.sql.ARRAY&lt;/a&gt;. It's used the
 same way as oracle.sql.STRUCT. We first create an &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e13995/oracle/sql/ArrayDescriptor.html" target="_blank"&gt;ArrayDescriptor&lt;/a&gt; instance
 using the JDBC connection and the type name. This helper object, the JDBC connection
 and a plain Java array are being  used to create the actual instance of &lt;b&gt;oracle.sql.ARRAY&lt;/b&gt;.
 And the code goes here ...
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;public&lt;/span&gt; class JavaFile {
  &lt;span style="color: slateblue;"&gt;public&lt;/span&gt; static ARRAY getFileList(String pFile) throws &lt;span style="color: slateblue;"&gt;Exception&lt;/span&gt; {
    Connection       con    = DriverManager.getConnection(&lt;span style="color: magenta;"&gt;"jdbc:default:connection:"&lt;/span&gt;);
    StructDescriptor sDescr = StructDescriptor.createDescriptor(&lt;span style="color: magenta;"&gt;"FILE_T"&lt;/span&gt;, con);
    ArrayDescriptor  aDescr = ArrayDescriptor.createDescriptor(&lt;span style="color: magenta;"&gt;"FILE_CT"&lt;/span&gt;, con);
    Object[]         o      = new Object[&lt;span style="color: magenta;"&gt;8&lt;/span&gt;];

    &lt;span style="color: blue;"&gt;/* Array containing java File objects */&lt;/span&gt;
    &lt;span style="color: slateblue;"&gt;File&lt;/span&gt;[]   f = new &lt;span style="color: slateblue;"&gt;File&lt;/span&gt;(pFile).listFiles();

    &lt;span style="color: blue;"&gt;/* Array containing SQL STRUCT objects */&lt;/span&gt;
    STRUCT[] a = new STRUCT[f.length];

    &lt;span style="color: blue;"&gt;/* now loop through the File array and create a STRUCT instance for each file */&lt;/span&gt;
    &lt;span style="color: slateblue;"&gt;for&lt;/span&gt; (int i=&lt;span style="color: magenta;"&gt;0&lt;/span&gt;;i&amp;lt;f.length;i++) {
     o[&lt;span style="color: magenta;"&gt;0&lt;/span&gt;] = f[i].getPath();
     o[&lt;span style="color: magenta;"&gt;1&lt;/span&gt;] = f[i].getName();
     o[&lt;span style="color: magenta;"&gt;2&lt;/span&gt;] = new BigDecimal(f[i].length());
     o[&lt;span style="color: magenta;"&gt;3&lt;/span&gt;] = new java.sql.Timestamp(f[i].lastModified());
     o[&lt;span style="color: magenta;"&gt;4&lt;/span&gt;] = (f[i].isDirectory()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;5&lt;/span&gt;] = (f[i].canWrite()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;6&lt;/span&gt;] = (f[i].canRead()?&lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;:&lt;span style="color: magenta;"&gt;"N"&lt;/span&gt;);
     o[&lt;span style="color: magenta;"&gt;7&lt;/span&gt;] = &lt;span style="color: magenta;"&gt;"Y"&lt;/span&gt;
     a[i] = new STRUCT(sDescr, con, o);
    } 
    &lt;span style="color: blue;"&gt;/* Create and return the ARRAY object which maps to the SQL type */&lt;/span&gt;
    &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; new ARRAY(aDescr, con, a);
  }
}
/
sho err

&lt;span style="color: #804040;"&gt;&lt;b&gt;create&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; replace &lt;span style="color: slateblue;"&gt;function&lt;/span&gt; get_file_list (p_file &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;) &lt;span style="color: slateblue;"&gt;return&lt;/span&gt; file_ct
&lt;span style="color: slateblue;"&gt;is&lt;/span&gt; language java name &lt;span style="color: magenta;"&gt;'JavaFile.getFileList(java.lang.String) return oracle.sql.ARRAY'&lt;/span&gt;;
/
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
As you see: This code is basically just a small extension of the code above. We loop through 
 the File[] array returned by &lt;a href="http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#listFiles%28%29" target="_blank"&gt;java.io.File.listFiles()&lt;/a&gt;, create an oracle.sql.STRUCT instance for each  
 java.io.File object and place it into a Java array (STRUCT[]). This java array is then being used
 to create the &lt;b&gt;oracle.sql.ARRAY&lt;/b&gt; instance,  which is finally passed back to PL/SQL. On the
 PL/SQL side we create the wrapper function and that's it. Try ...
&lt;br /&gt;
&lt;pre&gt;SQL&amp;gt; select file_name, last_modified, file_size from table(get_file_list('/'))

FILE_NAME                 LAST_MODIFIED        FILE_SIZE
------------------------- ------------------- ----------
wget-log                  27.04.2011 16:24:02        496
boot                      02.02.2011 13:22:58       1024
misc                      25.07.2011 09:29:09          0
stage                     04.04.2011 11:27:57          7
lib                       15.07.2011 11:06:27       4096
etc                       25.07.2011 09:29:07       4096
root                      15.07.2011 11:14:01       4096
bin                       02.02.2011 13:28:45       4096
:                         :                            :
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
It's quite simpe, isn't it? Using this approach you can pass any data structure between
 Java and PL/SQL - you can use any Java library you want. The only prerequisite is that
 your Java library does not depend on native code - it must be pure Java. 
 First you might design a simple interface consisting of static Java 
 methods which can be easily mapped to PL/SQL calls. Use simple, scalar types whenever
 possible and use object types and arrays only when you really need them. Then you
 need to implement the static java methods (using &lt;b&gt;STRUCT&lt;/b&gt; and &lt;b&gt;ARRAY&lt;/b&gt;, if necessary), 
 create the SQL object types and PL/SQL wrapper
 packages and you are done. The code packages for
 &lt;a href="http://plsqlexecoscomm.sourceforge.net/" target="_blank"&gt;filesystem access&lt;/a&gt;,
 zum &lt;a href="http://plsqlmailclient.sourceforge.net/" target="_blank"&gt;accessing POP3 or IMAP4 mail servers with PL/SQL&lt;/a&gt; or to&lt;a href="http://sql-plsql-de.blogspot.com/2010/11/zip-archive-einpacken-und-auspacken-das.html" target="_blank"&gt;pack and unpack ZIP archives&lt;/a&gt; all work that way. And as said: You can
 use integrate any Java library doing interesting stuff into the Oracle database. There are
 no limits.
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-6676452663001950262?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/PliOcPNTsb4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/PliOcPNTsb4/von-java-nach-sql-java-objekte-und-die.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1391265 11.5801863</georss:point><georss:box>47.969588 11.2643293 48.308665000000005 11.896043299999999</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/10/von-java-nach-sql-java-objekte-und-die.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-2501414756131811256</guid><pubDate>Fri, 16 Sep 2011 10:08:00 +0000</pubDate><atom:updated>2011-09-16T13:44:43.792+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">plsql</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">twitter</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>Twitter postings mit der Datenbank (SQL, PLSQL, Java)</title><description>&lt;div lang="en" style="color: #cc6600; display: none;"&gt;
Twitter postings by the database&lt;/div&gt;
&lt;div lang="de"&gt;
Seit einiger Zeit verwenden meine  Teamkollegen und ich den Twitter-Account 
&lt;a href="http://twitter.com/oraclebudb" target="_blank"&gt;@oraclebudb&lt;/a&gt;, um interessante
Neuerungen, die keine langen Texte erfordern, bekanntzumachen. Wenn Ihr also stets über 
Neuigkeiten zur Oracle-Datenbank wie 
neue Releases, Patchsets, deutschsprachige Veranstaltungen oder ähnliches informiert sein wollt,
einfach an diesen Account dranhängen ("Folgen").&lt;/div&gt;
&lt;div lang="de"&gt;
Nun ist man ab und zu unterwegs und kann einen Tweet nicht immer von seinem iPhone oder
PC absetzen - man möchte einen Tweet "planen" und dann zu einem festgelegten Zeitpunkt,
bspw. "Montag 10:00 Uhr" automatisch absetzen. Sowas kann übrigens auch sehr interessant
sein, wenn man Twitter für regelmäßige Statusmeldungen über etwas nutzen möchte - ich
könnte mir sehr gut vorstellen, zum Beispiel die Pegelstände von Flüssen (vor allem bei
Hochwasser) regelmäßig über Twitter zu posten. Auch hier braucht es einen Automatismus, von
Hand geht nix mehr.&lt;/div&gt;
&lt;div lang="de"&gt;
Der Nutzen ist klar - die Frage ist also: Wie setzt man es um? Und ich möchte es natürlich 
mit der Oracle-Datenbank, also mit SQL und PL/SQL machen. Eine erste Google-Suche führte
mich denn auch zu zahlreichen Blogs und Webseiten mit PL/SQL-Codefragmenten, die
alle eines gemein hatten: Ich brachte es nicht zum Laufen (wobei das wohl eher an mir lag)
Allein das von Twitter 
verwendete OAuth-Verfahren, welches von einer Anwendung genutzt werden &lt;i&gt;muss&lt;/i&gt;, implementiert
man nicht mal eben in 5 Minuten in PL/SQL.&lt;/div&gt;
&lt;div lang="de"&gt;
Im Java-Bereich gibt es allerdings eine sehr populäre Bibliothek für Twitter: 
&lt;a href="http://twitter4j.org/en/index.html" target="_blank"&gt;twitter4j&lt;/a&gt;. Und da
man in einer Oracle-Datenbank auch Java laufen lassen kann, habe ich mich entschlossen,
das Rad &lt;i&gt;nicht&lt;/i&gt; neu in PL/SQL zu erfinden, sondern das zu nutzen, was da ist ...&lt;/div&gt;
&lt;div lang="de"&gt;
Im folgenden findet Ihr also eine Anleitung, wie man eine PL/SQL-Prozedur in die
Datenbank legt, die unter einem bestimmten Account twittert. Mit dieser Variante
kann nur der Account-Eigentümer per PL/SQL twittern - die Autorisierung durch andere
Nutzer ist prinzipiell möglich, hier aber nicht beschrieben.&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;b&gt;Schritt 1: Applikation auf "dev.twitter.com" registrieren&lt;/b&gt;:&lt;/div&gt;
&lt;div lang="de"&gt;
Loggt euch mit eurem Twitter-Account auf &lt;a href="http://dev.twitter.com/" target="_blank"&gt;dev.twitter.com&lt;/a&gt;
ein. Navigiert im Menü oben rechts (dort, wo Ihr euren Accountnamen seht) zum Bereich
&lt;b&gt;My Applications&lt;/b&gt; und klickt dann die Schaltfläche &lt;b&gt;Create a new Application&lt;/b&gt;. Füllt dann den
Dialog aus. Ihr braucht einen Namen, eine Beschreibung und eine Webseite (die muss es für den
Anfang aber nicht wirklich geben). Die Callback-URL wird für heute nicht benötigt (Abbildung 1). Dann
müsst Ihr mit dem CAPTCHA fertig werden und eure Anwendung ist erstellt.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-EUbydMg1LC4/TnMeBD-xPsI/AAAAAAAAAH4/VKXn6aYNb0c/s1600/img01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="189" src="http://3.bp.blogspot.com/-EUbydMg1LC4/TnMeBD-xPsI/AAAAAAAAAH4/VKXn6aYNb0c/s320/img01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;i&gt;Abbildung 1: Anwendung erstellen&lt;/i&gt; &lt;/div&gt;
&lt;div lang="de"&gt;
Wenn die Anwendung erstellt wurde, seht Ihr bereits einige wichtige URLs und das
Schlüsselpaar für die Anwendung selbst (&lt;i&gt;Consumer Key&lt;/i&gt; und &lt;i&gt;Consumer Secret&lt;/i&gt;). 
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-IxCYFlxYZmA/TnMeBPDwT7I/AAAAAAAAAIA/1PzMC-2jVew/s1600/img02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="218" src="http://2.bp.blogspot.com/-IxCYFlxYZmA/TnMeBPDwT7I/AAAAAAAAAIA/1PzMC-2jVew/s320/img02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;i&gt;Abbildung 2: Die Anwendung wurde erstellt&lt;/i&gt; &lt;/div&gt;
&lt;div lang="de"&gt;
Nun navigiert Ihr zu den &lt;b&gt;Settings&lt;/b&gt; eurer neuen Anwendung und stellt die
Berechtigungen auf &lt;b&gt;Read and Write&lt;/b&gt;. Das ist wichtig, denn das Absenden eines 
Tweets ist ein "Write.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-I67plIM6yBY/TnMeBU7TCHI/AAAAAAAAAII/eBx4UeCco-I/s1600/img03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="175" src="http://2.bp.blogspot.com/-I67plIM6yBY/TnMeBU7TCHI/AAAAAAAAAII/eBx4UeCco-I/s320/img03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;i&gt;Abbildung 3: Vergeben der Berechtigung "Read and Write"&lt;/i&gt; &lt;/div&gt;
&lt;div lang="de"&gt;
Nun zurück zur ersten Reiterkarte &lt;b&gt;Details&lt;/b&gt;. Unten seht Ihr eine Schaltfläche
&lt;b&gt;Create My Access Token&lt;/b&gt; - damit generiert Ihr die
nötigen Accountschlüssel für den eigenen Account (&lt;i&gt;Access Token&lt;/i&gt; und &lt;i&gt;Access Token Secret&lt;/i&gt;).
Diese, den &lt;i&gt;Consumer Key&lt;/i&gt; und das &lt;i&gt;Consumer Secret&lt;/i&gt; bitte merken  - das 
brauchen wir in der Stored Procedure.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-cRvb8MddPTk/TnMeBpP0acI/AAAAAAAAAIQ/m7XUIaQb0ZI/s1600/img04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="224" src="http://4.bp.blogspot.com/-cRvb8MddPTk/TnMeBpP0acI/AAAAAAAAAIQ/m7XUIaQb0ZI/s320/img04.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;i&gt;Abbildung 4: Access Token und Access Token Secret&lt;/i&gt; &lt;/div&gt;
&lt;div lang="de"&gt;
Nun seid Ihr mit dem Registrieren der Anwendung fertig. Jetzt geht es zur Oracle-Datenbank.&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;b&gt;Schritt 2: Twitter4j in die Datenbank laden.&lt;/b&gt;&lt;/div&gt;
&lt;div lang="de"&gt;
Ladet &lt;b&gt;twitter4j&lt;/b&gt; von der Webseite &lt;a href="http://www.twitter4j.org/" target="_blank"&gt;twitter4j.org&lt;/a&gt;
herunter. Twitter4j ist Open Source unter der Apache Lizenz - kann also für alle Anwendungsfälle, sei
es kommerziell oder nicht, verwendet werden. Das ZIP-Archiv muss in ein Verzeichnis eurer Wahl
ausgepackt werden - am besten legt Ihr es gleich auf den Datenbankserver.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-JDCUZ2165c4/TnMeBioS0gI/AAAAAAAAAIY/aZvWFNm0jU0/s1600/img05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="241" src="http://2.bp.blogspot.com/-JDCUZ2165c4/TnMeBioS0gI/AAAAAAAAAIY/aZvWFNm0jU0/s320/img05.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;i&gt;Abbildung 5: ZIP Archiv "twitter4j"&lt;/i&gt; &lt;/div&gt;
&lt;div lang="de"&gt;
Die Java-Bibliotheken befinden sich im Unterverzeichnis &lt;b&gt;lib&lt;/b&gt;. Für einfache Status-Updates
braucht Ihr nur das Archiv &lt;b&gt;twitter4j-core-2.2.4.jar&lt;/b&gt;. Das wird nun wie folgt in die Datenbank geladen.
&lt;pre&gt;$ loadjava -user {dbuser}/{dbpassword} -o -r -v twitter4j-core-2.2.4.jar
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Ihr sehr nun einige Meldungen und zum Schluß kommen einige Fehlermeldungen, die Ihr
aber ignorieren könnt.
&lt;pre&gt;skipping : resource META-INF/maven/org.twitter4j/twitter4j-core/pom.xml
skipping : resource META-INF/maven/org.twitter4j/twitter4j-core/pom.properties
The following operations failed
    class twitter4j/internal/logging/SLF4JLogger: resolution
    class twitter4j/internal/logging/SLF4JLoggerFactory: resolution
exiting  : Failures occurred during processing
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;b&gt;Schritt 3: Java-Klasse für ein Status-Update erstellen&lt;/b&gt;&lt;/div&gt;
&lt;div lang="de"&gt;
Es wäre sehr aufwändig, die Methoden der Twitter4j-Bibliothek direkt auf PL/SQL abzubilden. Dafür
sind es zu viele und vielfach werden Java-Objekte übergeben, deren Mapping auf Datenbanktypen nicht
einfach ist. Der beste Weg ist es, die Operationen, die man haben möchte, in Java zu implementieren,
dabei einfache Funktionssignaturen zu verwenden und diese "Top-Level"-Methoden dann nach
PL/SQL abzubilden.  Zuerst also die Java-Klasse, die auf Basis der Twitter4j-Beispiele gebaut wurde. Achtet darauf,
in der Methode &lt;b&gt;setOAuthAccessToken&lt;/b&gt; die Schlüssel von &lt;b&gt;dev.twitter.com&lt;/b&gt; einzutragen. Weiter
vorne in den Calls zu &lt;b&gt;System.setProperty&lt;/b&gt; müsst Ihr euren Proxy-Server eintragen, wenn die Datenbank hinter einer
Firewall steht. Wenn nicht, entfernt die Zeilen einfach.
&lt;pre&gt;create or replace and compile java source named TwitterStatusUpdate as
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; twitter4j.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; twitter4j.conf.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; twitter4j.auth.*;

&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; java.io.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; java.util.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; oracle.jdbc.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; oracle.sql.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; java.sql.*;

&lt;span style="color: seagreen;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; UpdateStatus {
  &lt;span style="color: seagreen;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; Twitter twitter = &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;

  &lt;span style="color: seagreen;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt;  {
    System.setProperty(&lt;span style="color: magenta;"&gt;"http.proxyHost"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;i&gt;{Proxy-Server, falls nötig}&lt;/i&gt;"&lt;/span&gt;);
    System.setProperty(&lt;span style="color: magenta;"&gt;"http.proxyPort"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;i&gt;{Proxy-Server-Port, falls nötig}&lt;/i&gt;"&lt;/span&gt;);
  
    ConfigurationBuilder confbuilder  = &lt;span style="color: #804040;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; ConfigurationBuilder(); 
    confbuilder.setOAuthAccessToken(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Access-Token aus dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;) 
    .setOAuthAccessTokenSecret(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Access-Token-Secret aus dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;) 
    .setOAuthConsumerKey(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Consumer-Key aus dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;) 
    .setOAuthConsumerSecret(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Consumer-Secret aus dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;); 
    twitter = &lt;span style="color: #804040;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; TwitterFactory(confbuilder.build()).getInstance(); 
  }

  &lt;span style="color: seagreen;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; String updateStatus(String newStatus) &lt;span style="color: seagreen;"&gt;&lt;b&gt;throws&lt;/b&gt;&lt;/span&gt; Exception {
    Status status = twitter.updateStatus(newStatus);
    &lt;span style="color: #804040;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; status.getText();
  }
}
/
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;b&gt;Schritt 4: PL/SQL Wrapper für die Java-Methode erstellen&lt;/b&gt;&lt;/div&gt;
&lt;div lang="de"&gt;
Für diese statische Java-Metjode &lt;b&gt;updateStatus&lt;/b&gt;, die einen String entgegennimmt und zurückgibt, lässt
sich nun sehr einfach ein PL/SQL-Mapping erstellen.
&lt;pre&gt;&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;replace&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; set_twitter_status(p_new_status &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;language&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;java&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'UpdateStatus.updateStatus(java.lang.String) return java.lang.String'&lt;/span&gt;;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;b&gt;Schritt 5: Privilegienvergabe&lt;/b&gt;&lt;/div&gt;
&lt;div lang="de"&gt;
Ein Twitter-Posting wird über das Netzwerk abgesetzt - das darf ein "normaler" Datenbankuser mit
Java erstmal nicht. Damit die obige Java-Klasse auch tatsächlich funktioniert, muss der Datenbankuser
Privilegien zum Netzwerkzugriff und zum Einstellen des Proxy-Servers (falls nötig) erhalten. Das 
erledigt man wie folgt - das Skript muss als DBA gestartet werden.
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;begin&lt;/span&gt;
  dbms_java.grant_permission( 
    &lt;span style="color: magenta;"&gt;'{DB-SCHEMA}'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'SYS:java.util.PropertyPermission'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'http.proxyHost'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'read,write'&lt;/span&gt; 
  );
  dbms_java.grant_permission( 
    &lt;span style="color: magenta;"&gt;'{DB-SCHEMA}'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'SYS:java.util.PropertyPermission'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'http.proxyPort'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'read,write'&lt;/span&gt; 
  );
  dbms_java.grant_permission( 
    &lt;span style="color: magenta;"&gt;'{DB-SCHEMA}'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'SYS:java.net.SocketPermission'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'api.twitter.com:80'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'connect, resolve'&lt;/span&gt; 
  );
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt;;
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
&lt;b&gt;Abschluß&lt;/b&gt;&lt;/div&gt;
&lt;div lang="de"&gt;
Dann ist es fertig. Nun könnt Ihr testen ...
&lt;pre&gt;SQL&amp;gt; select set_twitter_status('another test at friday') from dual;

SET_TWITTER_STATUS('ANOTHERTESTATFRIDAY')
------------------------------------------------------------------------
another test at friday

1 Zeile wurde ausgewählt.
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="de"&gt;
Wenn Ihr euch die Twitter-Seite eures Accounts anseht, solltet Ihr das Posting nun
sehen ... und von hier aus ist eine Automatisierung kein Thema mehr - ob man nun
per Scheduler-Job regelmäßig etwas twittert, eine APEX-Anwendung zum Planen der Tweets
erstellt oder andere Dinge tut - mit den Mitteln der Datenbank kann dies nun beliebig
genutzt werden. Eine einfaches Beispiel ist demnach eine APEX-Anwendung mit einem Formular
auf eine Tabelle. Im Formular kann man Tweets und eine Zeitpunkt eintragen, zu dem der
Tweet gepostet werden soll. Ein DBMS_SCHEDULER-Job läuft dann regelmäßig los und postet
automatisch alle "fälligen" Tweets. Und natürlich kann man mit &lt;b&gt;twitter4j&lt;/b&gt; noch mehr tun als nur Status-Updates
abzusetzen, aber wie man bspw. die &lt;i&gt;Home-Timeline&lt;/i&gt; abruft, dazu mache ich am besten
ein eigenes Blog Posting. Viel Spaß auf jeden Fall beim Ausprobieren ...&lt;/div&gt;

&lt;div lang="en" style="display: none;"&gt;
My teammates and me are using the twitter account
&lt;a href="http://twitter.com/oraclebudb" target="_blank"&gt;@oraclebudb&lt;/a&gt;, to post interesting
news about the Oracle database (Events in german language, Releases and more) for a german
audience. So if you are a german reader and interested in regular updates about the
Oracle database, follow  &lt;a href="http://twitter.com/oraclebudb" target="_blank"&gt;@oraclebudb&lt;/a&gt;.
English readers might follow  &lt;a href="http://twitter.com/oracledatabase" target="_blank"&gt;@oracledatabase&lt;/a&gt;.&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
But sometimes one wants to schedule a tweet - perhaps for tomorrow at 10:00am. If one
wants to use Twitter for regular updates about something (think about floodwater levels for
a river) some kind of automation or scheduling is needed - manual tweets are not possible. 
So the question is: How to implement this? I'd like to do it with APEX, the Oracle database
and PL/SQL. So I asked Mr. Google how to do this and I got some PL/SQL fragments which I could
not manage to work on my system. But I saw that the "OAuth" mechanism which Twitter uses
for authenticating is something which I cannot implement in 5 minutes in PL/SQL.&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Java developers have  the very popular  &lt;a href="http://twitter4j.org/en/index.html" target="_blank"&gt;twitter4j&lt;/a&gt;.
library - and since the Oracle database can run Java Stored Procures I decided not to
reinvent the wheel and to use things already there (XE-Users: Sorry). The following
posting describes how to do automatic tweets from the Oracle database using the
Twitter4j library and some Java and PL/SQL coding with the "own" twitter account; the
library allows also authorization for other Twitter accounts - but this is not
described here.&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;b&gt;Step  1: Register your application on "dev.twitter.com"&lt;/b&gt;:&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Log into &lt;a href="http://dev.twitter.com/" target="_blank"&gt;dev.twitter.com&lt;/a&gt;
with your Twitter account. In the menu in the upper right corner (where you can see your
Twitter username) navigate to &lt;b&gt;My Applications&lt;/b&gt; and click on 
&lt;b&gt;Create a new Application&lt;/b&gt;. Then fill in the form. You need a name, a description
and a Website URL (which don't need to work for now). The callback URL is not needed - after
that manage the CAPTCA and your application is registered.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-EUbydMg1LC4/TnMeBD-xPsI/AAAAAAAAAH4/VKXn6aYNb0c/s1600/img01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="189" src="http://3.bp.blogspot.com/-EUbydMg1LC4/TnMeBD-xPsI/AAAAAAAAAH4/VKXn6aYNb0c/s320/img01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;i&gt;Register your application&lt;/i&gt; &lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
You now see the key pair (&lt;i&gt;Consumer Key&lt;/i&gt; and &lt;i&gt;Consumer Secret&lt;/i&gt;) for your
application. We will need that later on.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-IxCYFlxYZmA/TnMeBPDwT7I/AAAAAAAAAIA/1PzMC-2jVew/s1600/img02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="218" src="http://2.bp.blogspot.com/-IxCYFlxYZmA/TnMeBPDwT7I/AAAAAAAAAIA/1PzMC-2jVew/s320/img02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;i&gt; The application has been registered.&lt;/i&gt; &lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Now navigate to the &lt;b&gt;Settings&lt;/b&gt; tab and adjust the Privileges of your
Application. It will need
&lt;b&gt;Read and Write&lt;/b&gt; privileges, since a tweet is a "Write".
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-I67plIM6yBY/TnMeBU7TCHI/AAAAAAAAAII/eBx4UeCco-I/s1600/img03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="175" src="http://2.bp.blogspot.com/-I67plIM6yBY/TnMeBU7TCHI/AAAAAAAAAII/eBx4UeCco-I/s320/img03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;i&gt;Grant "Read and Write" privileges to the application&lt;/i&gt; &lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Then go back to the &lt;b&gt;Details&lt;/b&gt; tab and navigate down to the button named
&lt;b&gt;Create My Access Token&lt;/b&gt; - this will generate the keys for your account.
(&lt;i&gt;Access Token&lt;/i&gt; and &lt;i&gt;Access Token Secret&lt;/i&gt;). Our application has to
create a signature using the two application keys as well as the two account keys - but
the Twitter4j library will do the necessary stuff.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-cRvb8MddPTk/TnMeBpP0acI/AAAAAAAAAIQ/m7XUIaQb0ZI/s1600/img04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="224" src="http://4.bp.blogspot.com/-cRvb8MddPTk/TnMeBpP0acI/AAAAAAAAAIQ/m7XUIaQb0ZI/s320/img04.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Generated "Access Token" and "Access Token Secret"&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Now you're done with registering the application. We can now start the implementation
in the Oracle database.&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;b&gt;Step 2: Load the "twitter4j" library into the database.&lt;/b&gt;&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Download &lt;b&gt;twitter4j&lt;/b&gt; from &lt;a href="http://www.twitter4j.org/" target="_blank"&gt;twitter4j.org&lt;/a&gt;.
Twitter4j is Open Source software and it uses the Apache License. So you are free to use
for either commercial or non-commercial usage without a fee. Unpack the ZIP archive into
a folder of your choice - it's best to place it directly on the database server.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-JDCUZ2165c4/TnMeBioS0gI/AAAAAAAAAIY/aZvWFNm0jU0/s1600/img05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="241" src="http://2.bp.blogspot.com/-JDCUZ2165c4/TnMeBioS0gI/AAAAAAAAAIY/aZvWFNm0jU0/s320/img05.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;i&gt;Contents of the downloaded ZIP archive&lt;/i&gt; &lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
The java libraries are located in the subfolder &lt;b&gt;lib&lt;/b&gt;. For simple status updates (tweets)
the archive &lt;b&gt;twitter4j-core-2.2.4.jar&lt;/b&gt; is sufficient. Load it into the Oracle database as follows.
&lt;pre&gt;$ loadjava -user {dbuser}/{dbpassword} -o -r -v twitter4j-core-2.2.4.jar
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
You will see some error messages at the end of the loading process, which you can ignore.
&lt;pre&gt;skipping : resource META-INF/maven/org.twitter4j/twitter4j-core/pom.xml
skipping : resource META-INF/maven/org.twitter4j/twitter4j-core/pom.properties
The following operations failed
    class twitter4j/internal/logging/SLF4JLogger: resolution
    class twitter4j/internal/logging/SLF4JLoggerFactory: resolution
exiting  : Failures occurred during processing
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;b&gt;Step 3: Create a java method doing a status update&lt;/b&gt;&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
It would be a lot of work to map all the API methods to PL/SQL procedures and functions. There
are many methods and most of the have java objects in their signature. It's better to implement
the needed operations as Java methods with simple signatures and finally map those java methods
to PL/SQL. So the following code creates a simple java method "updateStatus" which can be 
mapped to PL/SQL very easily. This java code has been created based on the twitter4j examples, which
are also part of the downloaded archive. Note the placeholders for the key pairs from &lt;b&gt;dev.twitter.com&lt;/b&gt;
in the call of &lt;b&gt;setOAuthAccessToken&lt;/b&gt; which need to be replaced. The calls to &lt;b&gt;System.setProperty&lt;/b&gt; 
in the previous lines also contain placeholders for the proxy server and port, which also need to be adjusted to
your environment.
&lt;pre&gt;create or replace and compile java source named TwitterStatusUpdate as
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; twitter4j.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; twitter4j.conf.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; twitter4j.auth.*;

&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; java.io.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; java.util.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; oracle.jdbc.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; oracle.sql.*;
&lt;span style="color: #a020f0;"&gt;import&lt;/span&gt; java.sql.*;

&lt;span style="color: seagreen;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; UpdateStatus {
  &lt;span style="color: seagreen;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; Twitter twitter = &lt;span style="color: magenta;"&gt;null&lt;/span&gt;;

  &lt;span style="color: seagreen;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt;  {
    System.setProperty(&lt;span style="color: magenta;"&gt;"http.proxyHost"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;i&gt;{Proxy server, if required}&lt;/i&gt;"&lt;/span&gt;);
    System.setProperty(&lt;span style="color: magenta;"&gt;"http.proxyPort"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;i&gt;{Proxy server port, if required}&lt;/i&gt;"&lt;/span&gt;);
  
    ConfigurationBuilder confbuilder  = &lt;span style="color: #804040;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; ConfigurationBuilder(); 
    confbuilder.setOAuthAccessToken(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Access token from dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;) 
    .setOAuthAccessTokenSecret(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Access token secret from dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;) 
    .setOAuthConsumerKey(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Consumer key from dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;) 
    .setOAuthConsumerSecret(&lt;span style="color: magenta;"&gt;"&lt;i&gt;{Consumer secret from dev.twitter.com}&lt;/i&gt;"&lt;/span&gt;); 
    twitter = &lt;span style="color: #804040;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; TwitterFactory(confbuilder.build()).getInstance(); 
  }

  &lt;span style="color: seagreen;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; String updateStatus(String newStatus) &lt;span style="color: seagreen;"&gt;&lt;b&gt;throws&lt;/b&gt;&lt;/span&gt; Exception {
    Status status = twitter.updateStatus(newStatus);
    &lt;span style="color: #804040;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; status.getText();
  }
}
/
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;b&gt;Step 4: Create the PL/SQL wrapper&lt;/b&gt;&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
The created Java method "updateStatus" just takes and returns a java string. The mapping to SQL and
PL/SQL is, as already stated, very easy: 
&lt;pre&gt;&lt;span style="color: teal;"&gt;create&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: teal;"&gt;replace&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; set_twitter_status(p_new_status &lt;span style="color: #804040;"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;) &lt;span style="color: #804040;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: seagreen;"&gt;&lt;b&gt;varchar2&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: #804040;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;language&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;java&lt;/b&gt;&lt;/span&gt; &lt;span style="color: #804040;"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;'UpdateStatus.updateStatus(java.lang.String) return java.lang.String'&lt;/span&gt;;
&lt;span style="color: #804040;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;
sho err
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;b&gt;Step 5: Grant privileges&lt;/b&gt;&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Doing a tweet is a network request. A "normal" database user does not have privileges
to execute network operations in Java. To get the above java class actually working the
database schema needs java privileges to set the proxy server (if needed) and to do
the network operation. The following SQL script, which has to be executed with DBA privileges,
does the job.
&lt;pre&gt;&lt;span style="color: slateblue;"&gt;begin&lt;/span&gt;
  dbms_java.grant_permission( 
    &lt;span style="color: magenta;"&gt;'{DB-SCHEMA}'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'SYS:java.util.PropertyPermission'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'http.proxyHost'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'read,write'&lt;/span&gt; 
  );
  dbms_java.grant_permission( 
    &lt;span style="color: magenta;"&gt;'{DB-SCHEMA}'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'SYS:java.util.PropertyPermission'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'http.proxyPort'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'read,write'&lt;/span&gt; 
  );
  dbms_java.grant_permission( 
    &lt;span style="color: magenta;"&gt;'{DB-SCHEMA}'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'SYS:java.net.SocketPermission'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'api.twitter.com:80'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'connect, resolve'&lt;/span&gt; 
  );
&lt;span style="color: slateblue;"&gt;end&lt;/span&gt;;
/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
&lt;b&gt;Final testing&lt;/b&gt;&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
And then you are done. Try it ...
&lt;pre&gt;SQL&amp;gt; select set_twitter_status('another test at friday') from dual;

SET_TWITTER_STATUS('ANOTHERTESTATFRIDAY')
------------------------------------------------------------------------
another test at friday

1 row selected.
&lt;/pre&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
Point your browser to your twitter page - you should see that posing - done by SQL in
the Oracle database. From this point we can use this procedure as any other one. 
Creating a DBMS_SCHEDULER job is as easy as creating an APEX application from which
tweets are being posted. A simple example is an APEX application with a form on a table
where the user can enter a tweet and a timestamp at which to post the tweet. A DBMS_SCHEDULER
job runs in regular intervals an posts all tweets due. The twitter4j API allows much
more operations ... we could query the &lt;i&gt;Home Timeline&lt;/i&gt; and pass it back to the
SQL - but this is another story ... for another blog posting ...&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-2501414756131811256?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/NFZiMziqmjI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/NFZiMziqmjI/twitter-postings-mit-der-datenbank-sql.html</link><author>noreply@blogger.com (Carsten Czarski)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-EUbydMg1LC4/TnMeBD-xPsI/AAAAAAAAAH4/VKXn6aYNb0c/s72-c/img01.png" height="72" width="72" /><thr:total>0</thr:total><georss:featurename>München, Deutschland</georss:featurename><georss:point>48.1391265 11.5801863</georss:point><georss:box>47.969588 11.2643293 48.308665000000005 11.896043299999999</georss:box><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/09/twitter-postings-mit-der-datenbank-sql.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-176350039734377461</guid><pubDate>Fri, 02 Sep 2011 08:18:00 +0000</pubDate><atom:updated>2011-09-05T15:44:32.446+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">community</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">dbms_xplan</category><title>Ausführungspläne mit DBMS_XPLAN</title><description>&lt;div lang="de"&gt;Heute wollte ich eigentlich ein Blog-Posting über die verschiedenen Möglichkeiten von &lt;b&gt;DBMS_XPLAN&lt;/b&gt; bringen ... das kann ja wesentlich mehr als &lt;b&gt;DBMS_XPLAN.DISPLAY()&lt;/b&gt;. Es ist allein schon lohnenswert, sich die verschiedenen Varianten des Parameters &lt;b&gt;FORMAT&lt;/b&gt; anzusehen. Allerdings haben meine Kollegen, die die &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/apex/index.html" target="_blank"&gt;DBA Community-Seite&lt;/a&gt; betreiben, hierzu schon einiges geschrieben ... und man soll das Rad nicht neu erfinden. Daher verweise ich heute einfach nur auf den entsprechenden &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/dbms_xplan/index.html" target="_blank"&gt;Community-Tipp&lt;/a&gt;.  &lt;/div&gt;&lt;div lang="de"&gt;Viel Spaß beim Lesen!&lt;/div&gt;&lt;div lang="en" style="display: none;"&gt;My intention for today was a Blog Posting about the  &lt;b&gt;DBMS_XPLAN&lt;/b&gt; package - this package can do much more than just &lt;b&gt;DBMS_XPLAN.DISPLAY()&lt;/b&gt;. For instance - looking at the variants of the &lt;b&lt;FORMAT&lt;/b&gt; argument is worthful for its own. But the collegues maintaining the &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/apex/index.html" target="_blank"&gt;german DBA Community pages&lt;/a&gt; have done a lot of work on this, and I don't want to reinvent the wheel. German readers might just continue reading the &lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/dbms_xplan/index.html" target="_blank"&gt;Community How To on "Execution Plans"&lt;/a&gt;; english readers might try &lt;a href="http://translate.google.com/translate?sl=de&amp;tl=en&amp;js=n&amp;prev=_t&amp;hl=de&amp;ie=UTF-8&amp;layout=2&amp;eotf=1&amp;u=http%3A%2F%2Fwww.oracle.com%2Fwebfolder%2Ftechnetwork%2Fde%2Fcommunity%2Fdbadmin%2Ftipps%2Fdbms_xplan%2Findex.html" target="_blank"&gt;the "Google-Translate" version&lt;/a&gt;. &lt;/div&gt;&lt;div lang="en" style="display: none"&gt;Have fun!&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-176350039734377461?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/VzunbyYd9Pc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/VzunbyYd9Pc/ausfuhrungsplane-mit-dbmsxplan.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>1</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/09/ausfuhrungsplane-mit-dbmsxplan.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-1191902608750809537</guid><pubDate>Mon, 01 Aug 2011 08:10:00 +0000</pubDate><atom:updated>2011-08-01T09:19:33.262+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">UTL_HTTP</category><category domain="http://www.blogger.com/atom/ns#">httpuritype</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">browser</category><title>Der Browser in eurer Datenbank: HTTPURITYPE</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;The simple browser in your database: HTTPURITYPE&lt;/div&gt;
&lt;div lang="de"&gt;
 Wenn es darum geht, HTTP-Zugriffe aus der Datenbank heraus zu machen, ist das Paket
 UTL_HTTP natürlich das Mittel der Wahl - damit kann ein Browser komplett imitiert werden;
 vom Setzen der HTTP Header Felder oder von Cookies bis hin zu den HTTP Methoden GET und POST
 ist alles drin, was man braucht.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
  When it's about doing HTTP requests with PL/SQL - there's only one answer: UTL_HTTP. UTL_HTTP
  allows you to mimick a web browser completely in the database - one can set cookies, HTTP headers,
  do GET and POST requests and much more.
&lt;/div&gt;
&lt;div lang="de"&gt;
 In vielen Fällen braucht man das alles aber nicht - es muss einfach nur etwas per
 HTTP abgerufen werden. Und für genau diese Fälle gibt es die ganz einfache Variante: HTTPURITYPE - das
 kann man nutzen wie eine SQL-Funktion und es macht die ganze Arbeit auf einmal.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
  But in most cases these cool stuff is just not needed - all we want to do is a
  simple, plain HTTP request - no cookies, no special HTTP headers; nothing. And yes: There
  is a simple variant: HTTPURITYPE can be used like a SQL function and it does the whole
  work in one shot.
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
select httpuritype('http://sql-plsql-de.blogspot.com/feeds/posts/default') from dual
/

HTTPURITYPE('HTTP://SQL-PLSQL-DE.BLOGSPOT.COM/FEEDS/POSTS/DEFAULT')(URL)
--------------------------------------------------------------------------------
HTTPURITYPE('sql-plsql-de.blogspot.com/feeds/posts/default')

1 row selected.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Da passiert erstmal noch nix ... Los geht's, wenn Ihr den Content selbst mit
 GETBLOB(), GETCLOB() oder GETXML() abruft. 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
 Not much at the first glance. To have the database actually do the HTTP request you
 need to add one of the methods GETXML(), GETBLOB() or GETCLOB() ...
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
select httpuritype('http://sql-plsql-de.blogspot.com/feeds/posts/default').getxml() from dual
/

ERROR:
ORA-29273: HTTP-Anforderung nicht erfolgreich
ORA-06512: in "SYS.UTL_HTTP", Zeile 1819
ORA-12543: TNS: Ziel-Host ist nicht erreichbar
ORA-06512: in "SYS.HTTPURITYPE", Zeile 34
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Alles klar, dann setzen wir noch den Proxy ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
 Ok, ok ... go ahead and set the proxy server ...
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
begin
  utl_http.set_proxy('{proxy-host}:{proxy-port}');
end;
/

select httpuritype('http://sql-plsql-de.blogspot.com/feeds/posts/default').getxml() from dual
/

HTTPURITYPE('HTTP://SQL-PLSQL-DE.BLOGSPOT.COM/FEEDS/POSTS/DEFAULT').GETXML()
--------------------------------------------------------------------------------
&amp;lt;?xml version="1.0" encoding="CP850"?&amp;gt;
&amp;lt;?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?&amp;gt;

&amp;lt;?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.co
m/~d/styles/itemcontent.css"?&amp;gt;
&amp;lt;rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/
spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="htt
&amp;lt;/
&lt;/textarea&gt;
&lt;div lang="de"&gt;
  Voilá. HTTPURITYPE kann den Code wirklich ganz massiv
  vereinfachen - und wenn eine einfache Lösung ausreicht, dann soll man diese ja auch
  nutzen. Und als kleinen Exkurs kann man das Beispiel ja noch fortsetzen, indem man das
  XML auch direkt zerlegt ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
  And that's it - HTTPURITYPE is a great code simplification when it's about
  HTTP and PL/SQL. And we could continue this example and start to shred the XML we got
  back ...
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
with xml as (
  select httpuritype('http://sql-plsql-de.blogspot.com/feeds/posts/default').getxml() as doc
  from dual
)
select 
  t.titel,
  t.pubdate,
  t.link
from xml, xmltable(
  'for $i in //item return $i'
  passing xml.doc
  columns 
    titel   varchar2(100) path '/item/title/text()',
    pubdate varchar2(35)  path '/item/pubDate/text()',
    link    varchar2(500) path '/item/link/text()'
) t
/

TITEL                          PUBDATE                             LINK
------------------------------ ----------------------------------- ------------------------------
DELETE löscht ... und das ist  Mon, 18 Jul 2011 09:00:00 +0000     http://sql-plsql-de.blogspot.c
es, oder ...?                                                      om/2011/07/delete-loscht-und-d
                                                                   as-ist-es-oder.html

Schon gewusst ...? Multi Table Mon, 04 Jul 2011 11:46:00 +0000     http://sql-plsql-de.blogspot.c
 Insert                                                            om/2011/07/schon-gewusst-multi
                                                                   -table-insert.html

Kleine Statistikvorlesung: Mit Fri, 10 Jun 2011 09:11:00 +0000     http://sql-plsql-de.blogspot.c
 der Datenbank                                                     om/2011/06/kleine-statistikvor
&lt;/textarea&gt;
&lt;div lang="de"&gt;
  Einen RSS-Feed abholen und direkt zerlegen - mit nur einer SQL-Abfrage. Einfacher geht es nun
  wirklich nicht.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
 Fetching an RSS feed and parsing it into a database table with just one SQL query - there is no simpler
 way ...
&lt;/div&gt;
&lt;div lang="de"&gt;
 Ach ja ... fast hätte ich das vergessen. Ab Oracle11g braucht Ihr noch zusätzliche Netzwerk-Privilegien,
 damit Ihr aus der Datenbank überhaupt herauskommt: Mit dem PL/SQL-Paket &lt;b&gt;DBMS_NETWORK_ACL_ADMIN&lt;/b&gt;
 müsst Ihr uerem Datenbankuser für die einzelnen Netzwerkziele freischalten. Wie das geht, ist in
 &lt;a href="http://sql-plsql-de.blogspot.com/2008/11/mehr-sicherheit-in-oracle11g-plsql.html"
    target="_blank"&gt;diesem Blog-Posting&lt;/a&gt; beschrieben.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
 And (last but not lease) one important point: On Oracle11g (or higher) you need special
 networking privileges - EXECUTE on UTL_HTTP is not sufficient. Using the package &lt;b&gt;DBMS_NETWORK_ACL_ADMIN&lt;/b&gt;
 the DBA needs to enable the individual network "targets" for a specific database user. The
  &lt;a href="http://sql-plsql-de.blogspot.com/2008/11/mehr-sicherheit-in-oracle11g-plsql.html"
    target="_blank"&gt;blog posting&lt;/a&gt; describes the process.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-1191902608750809537?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/4tvSg6ElnMc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/4tvSg6ElnMc/der-browser-in-eurer-datenbank.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/08/der-browser-in-eurer-datenbank.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-228678808043232502</guid><pubDate>Fri, 29 Jul 2011 07:27:00 +0000</pubDate><atom:updated>2011-07-29T08:33:54.008+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ols_regression</category><title>Kleine Statistikvorlesung ... Fortsetzung auf einem neuen Blog</title><description>&lt;div style="display: none" lang="en"&gt;This posting is about a german only posting in another blog and therefore german only.&lt;/div&gt;
&lt;div lang="de"&gt;
Vor kurzem hatte ich ja das Blog Posting zum Thema &lt;a href="http://sql-plsql-de.blogspot.com/2011/06/kleine-statistikvorlesung-mit-der.html" target="_blank"&gt;Kleine Statistikvorlesung mit der Oracle-Datenbank&lt;/a&gt;, in dem ich die einfache lineare Regression gezeigt habe. In der Praxis ist aber öfter die anspruchsvollere multiple Regression mit mehreren Variablen gefordert, wozu es erstmal keine einfache SQL-Funktion gibt.
&lt;/div&gt;
&lt;div lang="de"&gt;
Aber die Datenbank kann es doch! Wie immer, eigentlich. &lt;b&gt;Thomas Uhren&lt;/b&gt; beschreibt &lt;a href="http://ora-sql-plsql.blogspot.com/"&gt;in seinem Blog&lt;/a&gt;, wie man das mit &lt;a href="http://ora-sql-plsql.blogspot.com/2011/07/multiple-regression-mit-olsregression.html"&gt;dem PL/SQL-Paket OLS_REGRESSION&lt;/a&gt; hinbekommen kann. Auf jeden Fall mal reinschauen. Viel Spaß beim Lesen.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-228678808043232502?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/RADtYiYMwEg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/RADtYiYMwEg/kleine-statistikvorlesung-fortsetzung.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/07/kleine-statistikvorlesung-fortsetzung.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-3233473695203425097</guid><pubDate>Mon, 18 Jul 2011 09:00:00 +0000</pubDate><atom:updated>2011-07-18T10:01:41.466+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">delete</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>DELETE löscht ... und das ist es, oder ...?</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;DELETE deletes ... that's it ...?&lt;/div&gt;
&lt;div lang="de"&gt;
 Ein SQL &lt;b&gt;DELETE&lt;/b&gt; löscht Zeilen von einer Tabelle - das ist bekannt. Und ein DELETE hat 
 eine WHERE-Klausel, die festlegt, welche Zeilen gelöscht werden sollen - das ist auch
 bekannt. 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
 A SQL DELETE statement deletes rows from a table - that is nothing new. And a DELETE also
 has a WHERE clause which determines the rows to delete from the table - this is also no
 news.
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
delete from emp where sal &amp;gt; 2000
/

6 rows deleted.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Doch was ist, wenn ich die Zeilen, die gelöscht werden sollen, nur durch einen
 Join mit einer anderen Tabelle ermitteln kann?  Als Beispiel möchte ich alle Mitarbeiter
 löschen, die in &lt;b&gt;DALLAS&lt;/b&gt; arbeiten. Das steht in der &lt;b&gt;EMP&lt;/b&gt;-Tabelle aber nicht drin - ich
 muss in die &lt;b&gt;DEPT&lt;/b&gt;-Tabelle gucken. Aus der soll aber nichts gelöscht werden ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 But what if I need to look into another table, to determine the rows to be deleted? 
 As an example, I would like to delete all rows representing
 employees based in &lt;b&gt;DALLAS&lt;/b&gt;. This information is not contained in the &lt;b&gt;EMP&lt;/b&gt; table. I need
 to look into &lt;b&gt;DEPT&lt;/b&gt; - but I do not want to delete anything from &lt;b&gt;DEPT&lt;/b&gt; ...
 &lt;/div&gt;
&lt;div lang="de"&gt;
 Es wird selten gemacht, aber man kann bei SQL DML-Kommandos anstelle einer
 Tabelle oder View (zur Wirkung von DML auf Views gibt es schon 
 &lt;a href="http://sql-plsql-de.blogspot.com/2009/07/views-und-dml-operationen-updatable.html"
    target="_blank"&gt;ein Blog-Posting&lt;/a&gt;) auch
 eine SQL-Abfrage verwenden. Ein einfaches Beispiel: Anstelle der Tabelle &lt;b&gt;EMP&lt;/b&gt; 
 setze ich ein SELECT ein.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
 It's not used very frequently - but you can use a SQL query in a SQL DML statement instead of a 
 table or view (
 regarding views and DML I already had 
 &lt;a href="http://sql-plsql-de.blogspot.com/2009/07/views-und-dml-operationen-updatable.html"
    target="_blank"&gt;a blog posting in 2010 Blog-Posting&lt;/a&gt;). A simple example: I'll
 replace the table &lt;b&gt;EMP&lt;/b&gt; with a SQL query.
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
delete from (select * from emp) where sal &amp;gt; 2000
/

6 rows deleted.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Das funktioniert genauso. Im Grunde genommen gilt von nun an das gleiche wie für
 &lt;a href="http://sql-plsql-de.blogspot.com/2009/07/views-und-dml-operationen-updatable.html" 
    target="_blank"&gt;DML-Kommandos auf Views&lt;/a&gt;.  Solange ein DML-Kommando auf eine View
 ohne INSTEAD OF Trigger funktioniert, kann man die View-Abfrage auch direkt ins DML aufnehmen.
 Also können wir die o.g. Aufgabenstellung wie folgt lösen:
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 This works - so we can try to use more complex subqueries in our DELETE statement. 
 Oracle, basically, applies the same rules as for using Views in DML statements - so 
 if a DML statement works on a view, (without an INSTEAD OF trigger) it will also work with
 the view query directly embedded into the DML command. So we can solve the initial
 problem as follows:
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
delete from (
  select empno from emp e join dept d on (e.deptno = d.deptno)
  where d.loc = 'DALLAS'
)
/

5 rows deleted.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Wenn ich das SQL wie oben formuliere, könnte man ja die Frage stellen,
 ob nicht aus beiden Tabellen Zeilen gelöscht werden - man verwendet ja auch beide Tabellen
 in der SQL-Abfrage. Hier ist Oracle aber recht eindeutig - zunächst löscht Oracle grundsätzlich nur aus
 &lt;i&gt;einer&lt;/i&gt; Basistabelle Zeilen (&lt;a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17120/views001.htm#i1006232" target="_blank"&gt;siehe Dokumentation: &lt;i&gt;General Rule&lt;/i&gt;&lt;/a&gt;). Dann
 stellt sich aber die Frage: &lt;i&gt;Wie&lt;/i&gt; entscheidet Oracle, aus welche Tabelle die Zeilen gelöscht
 werden sollen - warum nimmt Oracle die &lt;b&gt;EMP&lt;/b&gt;-Tabelle und nicht die &lt;b&gt;DEPT&lt;/b&gt;-Tabelle?
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt; 
 But now one question arises: If I have a SQL like the example above: from which 
 table will Oracle delete rows? The SQL query references the &lt;b&gt;EMP&lt;/b&gt; table 
 as well as &lt;b&gt;DEPT&lt;/b&gt;. So will
 Oracle delete rows from &lt;b&gt;EMP&lt;/b&gt; ... or from &lt;b&gt;DEPT&lt;/b&gt; ... or from &lt;i&gt;both&lt;/i&gt; ...?
 As a general rule, Oracle will delete rows from &lt;i&gt;only one&lt;/i&gt; base table (&lt;a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17120/views001.htm#i1006232" target="_blank"&gt;see the documentation: &lt;i&gt;General Rule&lt;/i&gt;&lt;/a&gt;). 
 But how does Oracle decide, from which table ...?
&lt;/div&gt; 
&lt;div lang="de"&gt;
 Hier kommt jetzt das Konzept der &lt;i&gt;Key-Preserved Table&lt;/i&gt; ins Spiel. In einem Join
 sind die Tabellen &lt;i&gt;Key-Preserved&lt;/i&gt;, die Ihre Schlüssel auch im Ergebnis des
 Joins behalten. Der obige Join ist so definiert, dass alle Zeilen der Tabelle &lt;b&gt;EMP&lt;/b&gt; 
 zurückgeliefert werden und die &lt;b&gt;DEPTNO&lt;/b&gt; dupliziert wird. Also 
 ist &lt;b&gt;EMPNO&lt;/b&gt; auch im Join-Ergebnis immer noch eindeutig. Für die Tabelle
 &lt;b&gt;DEPT&lt;/b&gt; sieht es anders aus - deren Schlüssel DEPTNO ist im Join-Ergebnis nicht mehr
 eindeutig. Wichtig ist, dass sich diese Eigenschaft nicht nach der tatsächlichen
 Ergebnismenge des Joins richtet, sondern nach dem konkreten Join und der Tabellendefinition
 im Datenbankschema. Daher gibt es in diesem Beispiel genau eine &lt;i&gt;Key-Preserved Table&lt;/i&gt; und
 aus der werden die Zeilen gelöscht.  Mehr zum Thema Key-Preserved Tables findet sich (wie immer)
 &lt;a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17120/views001.htm#ADMIN11783"
    target="_blank"&gt;in der Dokumentation&lt;/a&gt;.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 Now we need to look at the concept of a &lt;i&gt;Key-Preserved Table&lt;/i&gt;. In a join,
 the tables which &lt;i&gt;keep&lt;/i&gt; their unique key in the join result, are &lt;i&gt;Key-Preserved&lt;/i&gt;. In our
 example we have a join, which keeps all the rows from &lt;b&gt;EMP&lt;/b&gt; and which looks up
 values from &lt;b&gt;DEPT&lt;/b&gt;. So in the result the "key" &lt;b&gt;EMP.EMPNO&lt;/b&gt; is being &lt;i&gt;preserved&lt;/i&gt; 
 and "key" &lt;b&gt;DEPT.DEPTNO&lt;/b&gt; is lost (values were duplicated). So the table &lt;b&gt;EMP&lt;/b&gt; is 
 key-preserved in that join.  Note
 that this does &lt;i&gt;not&lt;/i&gt; depend on the actual result set data, but on the join itself and 
 the table definition
 in the database schema. So Oracle will delete rows from &lt;b&gt;EMP&lt;/b&gt; and not from &lt;b&gt;DEPT&lt;/b&gt;.
 More about Key-Preserved Tables can be found in the 
 &lt;a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17120/views001.htm#ADMIN11783"
    target="_blank"&gt;documentation&lt;/a&gt;.
&lt;/div&gt;
&lt;div lang="de"&gt;
 Nun sind auch andere Beispiele denkbar: ich möchte alle Zeilen aus &lt;b&gt;DEPT&lt;/b&gt; löschen,
 zu denen es keine Einträge in &lt;b&gt;EMP&lt;/b&gt; gibt. Hierzu brauche ich noch nicht einmal einen 
 Join.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 Another example - now without a join: I want to delete all rows from &lt;b&gt;DEPT&lt;/b&gt; 
 which habe no corresponding rows in &lt;b&gt;EMP&lt;/b&gt;.
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
 delete from (
  select deptno 
  from dept 
  where deptno not in (select deptno from emp)
)
/

1 row deleted.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Es bestätigt sich immer wieder: SQL ist eine unglaublich mächtige Sprache.
 Viele Dinge, die man prozedural recht aufwändig programmieren
 muss, lassen sich mit SQL sehr elegant erledigen ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 It proves all the time. SQL is a very powerful language - and many problems, which would
 require cumbersome procedural logic, can often be solved with simple, elegant SQL statements ...
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-3233473695203425097?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/07GozX57FRE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/07GozX57FRE/delete-loscht-und-das-ist-es-oder.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>2</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/07/delete-loscht-und-das-ist-es-oder.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-3795169014990778990</guid><pubDate>Mon, 04 Jul 2011 11:46:00 +0000</pubDate><atom:updated>2011-07-04T12:48:18.932+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">insert</category><title>Schon gewusst ...? Multi Table Insert</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;Did you know ..? Multi Table Insert&lt;/div&gt;
&lt;div lang="de"&gt;
 Normalerweise macht man ein SQL INSERT in genau eine Tabelle - die Syntax ist ja auch
 INSERT INTO {TABLE}. Wusstet Ihr, dass man mit einem SQL INSERT jedoch auch in meherer
 Tabellen gleichzeitig einfügen kann. Und ich meine nun nicht das SQL INSERT in eine
 VIEW und das Verteilen per INSTEAD-OF Trigger (hierzu gab es schonmal ein &lt;a href="http://sql-plsql-de.blogspot.com/2009/07/views-und-dml-operationen-updatable.html" target="_blank"&gt;Blog Posting&lt;/a&gt;.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;A SQL INSERT normally does the INSERT operation in exactly
 one table. Did you know that you also can insert data into multiple tables at the same time. And
 I do &lt;i&gt;not&lt;/i&gt; mean creating a view with an INSTEAD OF Trigger (there already was a &lt;a href="http://sql-plsql-de.blogspot.com/2009/07/views-und-dml-operationen-updatable.html?lang=en" target="_blank"&gt;Blog Posting&lt;/a&gt; about that.
&lt;/div&gt;
&lt;div lang="de"&gt;
 Nein, ich meine den sog. &lt;i&gt;Multi-Table-Insert&lt;/i&gt;. Dazu ein Beispiel. Zuerst erstellen 
 wir die Zieltabellen, die zugegebenermaßen recht einfach gestrickt sind, aber für ein einfaches
 Beispiel sollte das reichen ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;Today I'll talk about the &lt;i&gt;multi-table-insert&lt;/i&gt; feature of
 the Oracle database. This is best described with an example. First we will create some tables ...
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
create table emp10 as select empno, ename, job, hiredate, mgr, sal, comm from emp where 1=0
/

create table emp20 as select empno, ename, job, hiredate, mgr, sal, comm from emp where 1=0
/
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Und dann probieren wir unseren ersten &lt;i&gt;Multi Table Insert&lt;/i&gt;.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 And then we'll do our first &lt;i&gt;Multi Table Insert&lt;/i&gt;.
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
insert all
  into emp10 values (empno, ename, job, hiredate, mgr, sal, comm)
  into emp20 values (empno, ename, job, hiredate, mgr, sal, comm)
select * from emp
/

28 rows inserted.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
  Man sieht, dass danach beide Tabellen gefüllt sind - mit einem einzigen INSERT-Kommando. Doch
  das ist noch nicht alles. Wie man den Tabellennamen schon ansehen kann, möchten wir bestimmte
  Zeilen in bestimmte Tabellen haben ... und auch das geht mit dem Multi-Table-Insert.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 You'll see that both tables are being populated - with just &lt;i&gt;one&lt;/i&gt; SQL INSERT  command. But 
 this example was rather simple - As the table names indicate we want to have different rows
 from the source table into different target tables. That is no problem at all ...
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
insert all
  when deptno = 10 then 
    into emp10 values (empno, ename, job, hiredate, mgr, sal, comm)
  when deptno = 20 then
    into emp20 values (empno, ename, job, hiredate, mgr, sal, comm)
select * from emp
/

8 rows inserted.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Und auch das funktioniert - abhängig von der DEPTNO gehen die Zeilen in unterschiedliche
 Tabellen. Das kann noch mit einer ELSE-Anweisung kombiniert werden ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 That also works. And we can add an &lt;b&gt;ELSE&lt;/b&gt; clause to handle "all others".
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
create table emp_other as select empno, ename, job from emp where 1=0
/

insert all
  when deptno = 10 then 
    into emp10 values (empno, ename, job, hiredate, mgr, sal, comm)
  when deptno = 20 then
    into emp20 values (empno, ename, job, hiredate, mgr, sal, comm)
  else
    -- Here are the "other" ones - only EMPNO, ENAME and JOB
    into emp_other values (empno, ename, job)
select * from emp
/

14 rows inserted.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
  Bislang wurden stets alle WHEN-Klauseln beachtet - die Klauseln selbst schließen
  sich ja schon gegenseitig aus. Anders sieht es hier aus ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 In these examples Oracle evaluated &lt;i&gt;all&lt;/i&gt; &lt;b&gt;WHEN&lt;/b&gt; clauses. Even when a row
 was processed - the other WHEN clauses were also evaluated. So far this did not make
 a difference, because the WHEN clauses were mutually exclusive. In the next example
 we'll have table rows matching multiple WHEN clauses.
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
create table emp_highsal as select empno, ename, job, sal from emp where 1=0
/

insert all
  when sal &amp;gt; 3000 then 
    into emp_highsal values (empno, ename, job, sal)
  when deptno = 10 then
    into emp20 values (empno, ename, job, hiredate, mgr, sal, comm)
  when deptno = 20 then
    into emp20 values (empno, ename, job, hiredate, mgr, sal, comm)
  else
    -- Here are the "other" ones - only EMPNO, ENAME and JOB
    into emp_other values (empno, ename, job)
select * from emp
/

15 rows created.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
  &lt;b&gt;KING&lt;/b&gt; gehört zur DEPTNO &lt;b&gt;10&lt;/b&gt; und hat ein SAL größer als &lt;b&gt;3000&lt;/b&gt;. Er landet also
  sowohl in der Tabelle &lt;b&gt;EMP_HIGHSAL&lt;/b&gt;, als auch in &lt;b&gt;EMP10&lt;/b&gt;. 
  Unter Umständen sollen diejenigen Zeilen, die in &lt;b&gt;EMP_HIGHSAL&lt;/b&gt; eingefügt wurden,
  &lt;i&gt;nicht&lt;/i&gt; mehr weiter verarbeitet werden - es soll also nach der ersten passenden
  WHEN-Klausel aufgehört werden. Auch das geht - statt INSERT ALL schreiben wir dann
  INSERT FIRST. 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 &lt;b&gt;KING&lt;/b&gt; belongs to DEPTNO &lt;b&gt;10&lt;/b&gt; as well as the SAL is greater then &lt;b&gt;3000&lt;/b&gt;. So the
 row is inserted in both &lt;b&gt;EMP_HIGHSAL&lt;/b&gt; and &lt;b&gt;EMP10&lt;/b&gt;. But there might be cases where
 the row may only be inserted into &lt;i&gt;one&lt;/i&gt; table - evaluation shoud stop after the first
 matching &lt;b&gt;WHEN&lt;/b&gt; clause. To achieve this we use &lt;b&gt;INSERT FIRST&lt;/b&gt; instead of &lt;b&gt;INSERT ALL&lt;/b&gt;.
&lt;/div&gt;
&lt;textarea name="code" class="sql"&gt;
insert first
  when sal &amp;gt; 3000 then 
    into emp_highsal values (empno, ename, job, sal)
  when deptno = 10 then
    into emp20 values (empno, ename, job, hiredate, mgr, sal, comm)
  when deptno = 20 then
    into emp20 values (empno, ename, job, hiredate, mgr, sal, comm)
  else
    -- Here are the "other" ones - only EMPNO, ENAME and JOB
    into emp_other values (empno, ename, job)
select * from emp
/

14 rows created.
&lt;/textarea&gt;
&lt;div lang="de"&gt;
 Die Tatsache, dass viele INSERTs in einem Kommando abgearbeitet werden,
 kann die Performance bei großen Datenmengen extrem beeinflussen - denn die 
 Quelldaten werden beim Multi-Table-Insert nur einmal durchgearbeitet - würde man
 einzelne INSERT-Anweisungen machen, würden die Daten für &lt;i&gt;jedes INSERT&lt;/i&gt; einmal
 durchgescannt.  Mehr Info in der Dokumentation: &lt;a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e16579/transform.htm#i1006530" target="_blank"&gt;http://download.oracle.com/docs/cd/E11882_01/server.112/e16579/transform.htm#i1006530&lt;/a&gt;.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 Multi Table Inserts can impact performance significantly: If you have a very
 huge "source" dataset this is being scanned only once - Individual INSERT statements
 on the other hand would cause the database scan the source data once &lt;i&gt;for each&lt;/i&gt;
 INSERT statement. More information is available in the documentation: &lt;a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e16579/transform.htm#i1006530" target="_blank"&gt;http://download.oracle.com/docs/cd/E11882_01/server.112/e16579/transform.htm#i1006530&lt;/a&gt;.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-3795169014990778990?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/68dpyBbJucw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/68dpyBbJucw/schon-gewusst-multi-table-insert.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>2</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/07/schon-gewusst-multi-table-insert.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-7111375234277280356</guid><pubDate>Fri, 10 Jun 2011 09:11:00 +0000</pubDate><atom:updated>2011-06-10T10:14:23.265+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">Function</category><category domain="http://www.blogger.com/atom/ns#">statistic</category><category domain="http://www.blogger.com/atom/ns#">regression</category><category domain="http://www.blogger.com/atom/ns#">doag</category><title>Kleine Statistikvorlesung: Mit der Datenbank</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;Statistics lesson ... with the database&lt;/div&gt;
&lt;div lang="de"&gt;
 Heute machen wir eine kleine Statistikvorlesung - mit der Oracle-Datenbank. Es geht um
 die klassische, einfache lineare Regression. Das geht mit ganz einfachen SQL-Funktionen. Gegeben
 sei eine Tabelle, welche die getätigten Umsätze und die Ausgaben für TV-Werbung enthält.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 Today we'll have a tiny "statistics lesson" - with the Oracle Database. We'll do a simple
 linear regression, just by using SQL functions. Let's start with a simple table containing
 numbers for revenue and advertising cost by month.
&lt;/div&gt;
&lt;pre&gt;
MONAT      UMSATZ_EUR WERBUNG_TV_EUR
---------- ---------- --------------
2009/11        130000          14000
2009/12        140000          13200
2010/01        100000           9000
2010/02        103000           9500
2010/03        112000          10000
2010/04         90000          12000
2010/05         98000          13000
2010/06         70000           4000
2010/07        109010          12000
2010/08        120000          10000
2010/09        130000           9000
2010/10        150000          15000
2010/11        170000          18000
2010/12        200000          18000
2011/01                        10000
2011/02                        10200
2011/03                        15200
&lt;/pre&gt;
&lt;div lang="de"&gt;
 Die Statistikaufgabe wäre nun, den Umsatz der ersten drei Monate in 2011 anhand der
 Ausgaben für TV-Werbung zu prognostizieren - eine schöne Statistikaufgabe. Und für diesen
 Fall brauchen wir gar keinen Export nach Excel oder in eine Statistiksoftware - das
 machen wir direkt mit SQL ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 The exercise is now to forecast the revenue for 2011 - based on the spendings for
 TV advertising. This is a "classic" statistics exercise. And we don't need to export the
 data to Excel or to another statistics software - we'll do the job with SQL ...
&lt;/div&gt;
&lt;div lang="de"&gt;
 Zunächst stellen wir mit der "Methode der kleinsten Quadrate" den "Betrag" und die
 Steigung der linearen Funktion fest:
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 First we calculate the intercept and slope of the regression function using the
 &lt;i&gt;"least squares method"&lt;/i&gt;:
&lt;/div&gt;
&lt;pre&gt;
select 
   &lt;span style="color: red"&gt;REGR_INTERCEPT(UMSATZ_EUR, WERBUNG_TV_EUR)&lt;/span&gt; as A,
   &lt;span style="color: red"&gt;REGR_SLOPE(UMSATZ_EUR, WERBUNG_TV_EUR)&lt;/span&gt;     as B
from verkauf
&lt;/pre&gt;
&lt;div lang="de"&gt;
 Wenn man das dann in eine &lt;i&gt;Inline View&lt;/i&gt; packt (&lt;b&gt;WITH&lt;/b&gt;-Klausel), dann kann man
 Analyse und Prognose direkt mit einer SQL-Abfrage machen ...
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 Then we put this into an &lt;i&gt;inline view&lt;/i&gt; (&lt;b&gt;WITH&lt;/b&gt; clause) - so that we can
 do the analysis as well as the forecast in one SQL query ...
&lt;/div&gt;
&lt;pre&gt;
with regr_koeffizienten as (
 select 
   REGR_INTERCEPT(UMSATZ_EUR, WERBUNG_TV_EUR) as A,
   REGR_SLOPE(UMSATZ_EUR, WERBUNG_TV_EUR)     as B
 from verkauf
)
select 
  monat,
  umsatz_eur,
  werbung_tv_eur,
  a + b * WERBUNG_TV_EUR as UMSATZ_PROGNOSE
from VERKAUF, REGR_KOEFFIZIENTEN
/

MONAT      UMSATZ_EUR WERBUNG_TV_EUR UMSATZ_PROGNOSE
---------- ---------- -------------- ---------------
2009/11        130000          14000          138784
2009/12        140000          13200          132751
2010/01        100000           9000          101076
2010/02        103000           9500          104847
2010/03        112000          10000          108618
2010/04         90000          12000          123701
2010/05         98000          13000          131243
2010/06         70000           4000           63368
2010/07        109010          12000          123701
2010/08        120000          10000          108618
2010/09        130000           9000          101076
2010/10        150000          15000          146326
2010/11        170000          18000          168950
2010/12        200000          18000          168950
2011/01                        10000          108618
2011/02                        10200          110126
2011/03                        15200          147834
&lt;/pre&gt;
&lt;div lang="de"&gt;
 Stellt man das dann in APEX mit Hilfe eines Diagramms dar, ergibt sich
 ein schönes, quasi klassisches Statistikbild mit tatsächlichen und
 prognostizierten Daten. 
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 Then we could create an APEX application showing those numbers in 
 a nice chart.
&lt;/div&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-15XiQVx4UdM/TfHgTj1bW4I/AAAAAAAAAHw/9lck7dxWx78/s1600/Snap1.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://1.bp.blogspot.com/-15XiQVx4UdM/TfHgTj1bW4I/AAAAAAAAAHw/9lck7dxWx78/s320/Snap1.png" alt="" id="BLOGGER_PHOTO_ID_5616516836949187458" border="0" /&gt;&lt;/a&gt;
&lt;div lang="de"&gt;
 Man sieht sehr schön: Die Datenbank kann eine ganze Menge - und auch für
 diese einfachen Fälle gibt es Anwendungsmöglichkeiten. Die Datenbank kann
 seit 11g sogar die komplexere multiple Regression mit mehreren unabhängigen
 Variablen - das ist dann aber Bestandteil der &lt;i&gt;Data Mining Option&lt;/i&gt;, die
 man separat lizensieren muss. Wäre ein Fall für ein anderes Blog-Posting.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 It's still true: the Oracle database can do more than most of us think. And many
 tasks are more than simple. The database is even capable to do the more complex
 linear regression with multiple input variables - but this is then part of the
 &lt;i&gt;Data Mining Option&lt;/i&gt; which requires a separate license. That might be 
 topic of another blog posting.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-7111375234277280356?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/BQOaxHGe_fA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/BQOaxHGe_fA/kleine-statistikvorlesung-mit-der.html</link><author>noreply@blogger.com (Carsten Czarski)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-15XiQVx4UdM/TfHgTj1bW4I/AAAAAAAAAHw/9lck7dxWx78/s72-c/Snap1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/06/kleine-statistikvorlesung-mit-der.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-1542743378116617111</guid><pubDate>Mon, 06 Jun 2011 12:30:00 +0000</pubDate><atom:updated>2011-06-06T13:36:21.593+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">datenbank</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">treffen</category><title>Fundgrube Standard-Edition - und nicht nur das: DOAG SIG Development am 9. Juni</title><description>&lt;div lang="de"&gt;So .. der Urlaub ist rum und man ist zurück im Oracle-Leben. Ein technisches Posting habe ich heute noch nicht (das kommt später), aber ich kann wenigstens was ankündigen. Am &lt;b&gt;9. Juni&lt;/b&gt; (das ist am Donnerstag) bin ich mit zwei Vorträgen auf
der &lt;a href="http://mydoag.doag.org/termine/termine.php?tid=417441" target="_blank"&gt;DOAG SIG Development&lt;/a&gt; vertreten. Zum einen spreche ich über die "Fundgrube" Oracle Standard Edition (die vielen DB-Features und deren sinnvolle Kombination ist ja mein Lieblingsthema) und zum anderen spreche ich kurz über den neuen SQL Developer 3.0.
&lt;/div&gt;
&lt;div lang="de"&gt;Naja - und viel wichtiger ist natürlich der Austausch und die Diskussion in der Community. Insofern hoffe ich auf zahlreiche Teilnehmer, gute Diskussionen und ... veilleicht sieht man sich ja.&lt;/div&gt;
&lt;div lang="en" style="display: none"&gt;This posting is about an event in german language and therefore in german only.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-1542743378116617111?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/pDThB-Aaan8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/pDThB-Aaan8/fundgrube-standard-edition-und-nicht.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/06/fundgrube-standard-edition-und-nicht.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-4701412087240673333</guid><pubDate>Fri, 20 May 2011 13:30:00 +0000</pubDate><atom:updated>2011-05-20T14:36:30.699+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">apex</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">workshop</category><title>APEX Hands-On Workshop am 7. Juni in Jena</title><description>&lt;div lang="de"&gt;
Am 7. Juni veranstalten meine Kollegen &lt;b&gt;Karin Patenge&lt;/b&gt; und &lt;b&gt;Michal Soszynski&lt;/b&gt; einen APEX Hands On Workshop - in Zusammenarbeit mit der DOAG Regionalgruppe Thüringen. Also die Gelegenheit für APEX-Einsteiger im Raum Jena. Inhalte sind:
&lt;ul&gt;
&lt;li&gt;Die Oracle Datenbank als Entwicklungswerkzeug&lt;/li&gt;
&lt;li&gt;Arbeiten mit APEX Workspaces&lt;/li&gt;
&lt;li&gt;Von der Tabelle zur Applikation&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Import von Tabellendaten&lt;/li&gt;
&lt;li&gt;Erstellen einer Anwendung&lt;/li&gt;
&lt;li&gt;Ausführen einer Anwendung&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Erweitern und Ändern von Anwendungen&lt;/li&gt;
&lt;li&gt;Berechtigungskonzepte in APEX&lt;/li&gt;
&lt;li&gt;Das Layout von APEX-Anwendungen&lt;/li&gt;
&lt;/ul&gt;
Wer Interesse hat, also am besten gleich anmelden - Mehr Info und Anmeldedetails hier:&lt;br/&gt;
&lt;a href="http://www.oracle.com/webfolder/technetwork/de/community/apex/event/workshop/APEX_HandsOnWorkshop_Jena_20110607.pdf"&gt;http://www.oracle.com/webfolder/technetwork/de/community/apex/event/workshop/APEX_HandsOnWorkshop_Jena_20110607.pdf&lt;/a&gt;
&lt;/div&gt;
&lt;div lang="en" style="display: none"&gt;This posting is about an event in german language and therefore in german only.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-4701412087240673333?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/jqy0XKYA1Fc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/jqy0XKYA1Fc/apex-hands-on-workshop-am-7-juni-in.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>0</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/05/apex-hands-on-workshop-am-7-juni-in.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3592984248764138907.post-288552500833195687</guid><pubDate>Wed, 20 Apr 2011 08:26:00 +0000</pubDate><atom:updated>2011-04-20T09:26:28.651+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sqlplus</category><category domain="http://www.blogger.com/atom/ns#">kalender</category><category domain="http://www.blogger.com/atom/ns#">doag</category><category domain="http://www.blogger.com/atom/ns#">Skript</category><title>Ein wenig Spielerei: Monatskalender in SQL Plus!</title><description>&lt;div lang="en" style="display: none; color:#cc6600"&gt;Playing around a bit: Monthly calendar in SQL*Plus&lt;/div&gt;
&lt;div lang="de"&gt;
 Heute habe ich etwas, was wohl auch ein wenig in die Kategorie "Spielereien" gehört,
 aber die muss es ja auch geben. 
 Zuletzt hatte ich mal ein paar Minuten und dachte mir, dass ein SQL-Skript zum
 Generieren eines Monatskalenders doch ganz nett wäre - die Grundversion mit
 der &lt;b&gt;PIVOT&lt;/b&gt;-Klausel war schnell erstellt - dann fehlte nur noch der Feinschliff.
 Und hier ist es.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 My today's blog posting might be something for the toybox - but we also need those
 things. Last week I had some spare minutes in which I was playing around with the
 &lt;b&gt;SQL PIVOT&lt;/b&gt; clause introduced in Oracle11g. So I created a monthly calendar as 
 a SQL script. Here we go.
&lt;/div&gt;
&lt;pre&gt;
ol monat format a15
&lt;font color="#804040"&gt;&lt;b&gt;set&lt;/b&gt;&lt;/font&gt; pages &lt;font color="#ff00ff"&gt;20&lt;/font&gt;
&lt;font color="#804040"&gt;&lt;b&gt;set&lt;/b&gt;&lt;/font&gt; verify off

&lt;font color="#6a5acd"&gt;with&lt;/font&gt; dates &lt;font color="#6a5acd"&gt;as&lt;/font&gt; (
  &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt;  to_date(&lt;font color="#ff00ff"&gt;'01&amp;amp;1'&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'DDMMYYYY'&lt;/font&gt;) + (&lt;font color="#6a5acd"&gt;level&lt;/font&gt; - &lt;font color="#ff00ff"&gt;1&lt;/font&gt;) the_date &lt;font color="#6a5acd"&gt;from&lt;/font&gt; dual
  &lt;font color="#6a5acd"&gt;connect&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; &lt;font color="#6a5acd"&gt;level&lt;/font&gt; &amp;lt; trunc((add_months(to_date(&lt;font color="#ff00ff"&gt;'01&amp;amp;2'&lt;/font&gt;,&lt;font color="#ff00ff"&gt;'DDMMYYYY'&lt;/font&gt;),&lt;font color="#ff00ff"&gt;1&lt;/font&gt;) - &lt;font color="#ff00ff"&gt;1&lt;/font&gt;) - to_date(&lt;font color="#ff00ff"&gt;'01&amp;amp;1'&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'DDMMYYYY'&lt;/font&gt;)) + &lt;font color="#ff00ff"&gt;2&lt;/font&gt; 
) 
&lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; monat, &lt;font color="#ff00ff"&gt;&amp;quot; MO &amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot; DI &amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot; MI &amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot; DO &amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot; FR &amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot; SA &amp;quot;&lt;/font&gt;, &lt;font color="#ff00ff"&gt;&amp;quot; SO &amp;quot;&lt;/font&gt;, ww KW 
&lt;font color="#6a5acd"&gt;from&lt;/font&gt; (
  &lt;font color="#804040"&gt;&lt;b&gt;select&lt;/b&gt;&lt;/font&gt; 
    rtrim(to_char(the_date, &lt;font color="#ff00ff"&gt;'MONTH'&lt;/font&gt; ), &lt;font color="#ff00ff"&gt;'nls_date_language=german'&lt;/font&gt;)  monat 
   ,case 
      when to_char(the_date, &lt;font color="#ff00ff"&gt;'IW'&lt;/font&gt;) &amp;gt; &lt;font color="#ff00ff"&gt;50&lt;/font&gt; &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; to_char(the_date, &lt;font color="#ff00ff"&gt;'MM'&lt;/font&gt;) = &lt;font color="#ff00ff"&gt;'01'&lt;/font&gt; &lt;font color="#6a5acd"&gt;then&lt;/font&gt; 
        to_char(the_date, &lt;font color="#ff00ff"&gt;'YYYY'&lt;/font&gt;) - &lt;font color="#ff00ff"&gt;1&lt;/font&gt;||to_char(the_date, &lt;font color="#ff00ff"&gt;'IW'&lt;/font&gt;)
      &lt;font color="#6a5acd"&gt;else&lt;/font&gt; 
        to_char(the_date, &lt;font color="#ff00ff"&gt;'YYYYIW'&lt;/font&gt;)
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; yyyyww
   ,to_char(the_date, &lt;font color="#ff00ff"&gt;'yyyyMM'&lt;/font&gt; ) m 
   ,case when trunc(the_date) = trunc(&lt;font color="#804040"&gt;&lt;b&gt;sysdate&lt;/b&gt;&lt;/font&gt;) &lt;font color="#6a5acd"&gt;then&lt;/font&gt; 
      &lt;font color="#ff00ff"&gt;'*'&lt;/font&gt; || to_char(the_date, &lt;font color="#ff00ff"&gt;'DD'&lt;/font&gt;) || &lt;font color="#ff00ff"&gt;'*'&lt;/font&gt; 
    &lt;font color="#6a5acd"&gt;else&lt;/font&gt; 
      &lt;font color="#ff00ff"&gt;' '&lt;/font&gt; || to_char(the_date, &lt;font color="#ff00ff"&gt;'DD'&lt;/font&gt;) || &lt;font color="#ff00ff"&gt;' '&lt;/font&gt;
    &lt;font color="#6a5acd"&gt;end&lt;/font&gt; dd
   ,rtrim(upper(to_char(the_date, &lt;font color="#ff00ff"&gt;'DY'&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'nls_date_language=''german'''&lt;/font&gt; )))  d 
   ,to_char(the_date, &lt;font color="#ff00ff"&gt;'IW'&lt;/font&gt;) ww
  &lt;font color="#6a5acd"&gt;from&lt;/font&gt; dates &lt;font color="#6a5acd"&gt;where&lt;/font&gt; the_date &lt;font color="#804040"&gt;&lt;b&gt;between&lt;/b&gt;&lt;/font&gt; to_date(&lt;font color="#ff00ff"&gt;'01&amp;amp;1'&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'DDMMYYYY'&lt;/font&gt;) &lt;font color="#804040"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/font&gt; add_months(to_date(&lt;font color="#ff00ff"&gt;'01&amp;amp;2'&lt;/font&gt;, &lt;font color="#ff00ff"&gt;'DDMMYYYY'&lt;/font&gt;),&lt;font color="#ff00ff"&gt;1&lt;/font&gt;) - &lt;font color="#ff00ff"&gt;1&lt;/font&gt;
) pivot (
  min(dd) &lt;font color="#6a5acd"&gt;for&lt;/font&gt; d &lt;font color="#804040"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt; (
    &lt;font color="#ff00ff"&gt;'MO'&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#ff00ff"&gt;&amp;quot; MO &amp;quot;&lt;/font&gt;,
    &lt;font color="#ff00ff"&gt;'DI'&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#ff00ff"&gt;&amp;quot; DI &amp;quot;&lt;/font&gt;,
    &lt;font color="#ff00ff"&gt;'MI'&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#ff00ff"&gt;&amp;quot; MI &amp;quot;&lt;/font&gt;,
    &lt;font color="#ff00ff"&gt;'DO'&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#ff00ff"&gt;&amp;quot; DO &amp;quot;&lt;/font&gt;,
    &lt;font color="#ff00ff"&gt;'FR'&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#ff00ff"&gt;&amp;quot; FR &amp;quot;&lt;/font&gt;,
    &lt;font color="#ff00ff"&gt;'SA'&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#ff00ff"&gt;&amp;quot; SA &amp;quot;&lt;/font&gt;,
    &lt;font color="#ff00ff"&gt;'SO'&lt;/font&gt; &lt;font color="#6a5acd"&gt;as&lt;/font&gt; &lt;font color="#ff00ff"&gt;&amp;quot; SO &amp;quot;&lt;/font&gt; 
  )
)
&lt;font color="#6a5acd"&gt;order&lt;/font&gt; &lt;font color="#6a5acd"&gt;by&lt;/font&gt; yyyyww, m
/

undefine &lt;font color="#ff00ff"&gt;1&lt;/font&gt;
undefine &lt;font color="#ff00ff"&gt;2&lt;/font&gt;
&lt;/pre&gt;
&lt;div lang="de"&gt;
 Aufrufen geht dann so.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;Use it as follows ...&lt;/div&gt;
&lt;pre&gt;
SQL&amp;gt; @kal 042011 052011

MONAT            MO   DI   MI   DO   FR   SA   SO  KW
--------------- ---- ---- ---- ---- ---- ---- ---- --
APRIL                                01   02   03  13
APRIL            04   05   06   07   08   09   10  14
APRIL            11   12   13   14   15   16   17  15
APRIL           *18*  19   20   21   22   23   24  16
APRIL            25   26   27   28   29   30       17
MAI                                            01  17
MAI              02   03   04   05   06   07   08  18
MAI              09   10   11   12   13   14   15  19
MAI              16   17   18   19   20   21   22  20
MAI              23   24   25   26   27   28   29  21
MAI              30   31                           22
&lt;/pre&gt;
&lt;div lang="de"&gt;
 Bei der schnellen Terminplanung vielleicht ganz nützlich - nehmt's ansonsten als
 Beispiel für "Kunst mit SQL Plus". Bei mir liegt es neben einigen anderen
 Skripten im Verzeichnis, auf das die Umgebungsvariable &lt;b&gt;SQLPATH&lt;/b&gt; zeigt; damit habe
 ich es immer im Zugriff.
&lt;/div&gt;
&lt;div lang="en" style="display: none;"&gt;
 Perhaps it is useful, perhaps it's just SQL*Plus arts.  I placed it in the &lt;b&gt;SQLPATH&lt;/b&gt; folder
 where it is always accessible. Have fun.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3592984248764138907-288552500833195687?l=sql-plsql-de.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SqlUndPlsqlInOracle/~4/7oPEYKnc_m8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SqlUndPlsqlInOracle/~3/7oPEYKnc_m8/ein-wenig-spielerei-monatskalender-in.html</link><author>noreply@blogger.com (Carsten Czarski)</author><thr:total>2</thr:total><feedburner:origLink>http://sql-plsql-de.blogspot.com/2011/04/ein-wenig-spielerei-monatskalender-in.html</feedburner:origLink></item></channel></rss>

