<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>plsql &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/plsql/</link>
	<description>Feed of posts on WordPress.com tagged "plsql"</description>
	<pubDate>Sun, 29 Nov 2009 10:37:39 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Oracle PL/SQL unit testing with Ruby]]></title>
<link>http://blog.rayapps.com/2009/11/27/oracle-plsql-unit-testing-with-ruby/</link>
<pubDate>Fri, 27 Nov 2009 12:18:39 +0000</pubDate>
<dc:creator>Raimonds Simanovskis</dc:creator>
<guid>http://blog.rayapps.com/2009/11/27/oracle-plsql-unit-testing-with-ruby/</guid>
<description><![CDATA[Current PL/SQL unit testing options Unit testing and TDD (test driven development) practices are now]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><h3>Current PL/SQL unit testing options</h3>
<p>Unit testing and TDD (test driven development) practices are nowadays one of the key software development practices. It is especially important if you are doing agile software development in small iterations where you need to automate unit testing as much as possible, as you cannot do manual regression testing of all existing and new functionality at the end of each iteration.</p>
<p>In some languages (like Java, Ruby, Python, C# etc.) there is quite good tools and frameworks support for unit testing and as a result there is quite high testing culture among top developers in these communities. But unfortunately in PL/SQL community so far automated unit testing is not used very often. During recent Oracle OpenWorld conference in presentations about unit testing when it was asked who is doing automated unit testing then only few hands were raised.</p>
<p>Why is it so? And what are current options for doing automated PL/SQL unit testing?</p>
<p>The first unit testing framework for PL/SQL was <a href="http://utplsql.sourceforge.net/">utPLSQL</a> which was created by <a href="http://www.toadworld.com/sf">Steven Feuerstein</a> and based on API defined by many other xUnit style frameworks (like e.g. JUnit). But the issue with this approach was that PL/SQL syntax for tests was quite verbose and tests were not very readable (see <a href="http://utplsql.cvs.sourceforge.net/viewvc/utplsql/examples/ut_betwnstr.pkb?view=markup">example</a>). As a result Steven stopped developing further utPLSQL and currently there are no other active maintainers of this project. There are some other alternative frameworks which tried to simplify writing tests in PL/SQL (OUnit, pl/unit, PLUTO etc.) but none of them are very actively used and maintained by PL/SQL community.</p>
<p>Because of the issues with utPLSQL Steven Feuerstein started development of graphical interface tool for PL/SQL unit testing which is now <a href="http://unittest.inside.quest.com">Quest Code Tester for Oracle</a>. This tool is actively developed and maintained by Quest Software but there are several issues with it:</p>
<ul>
<li>It is a commercial tool and as a result it will not become widely accepted by all PL/SQL developers. There is also a freeware edition of it but the functionality of it is <a href="http://unittest.inside.quest.com/servlet/KbServlet/download/2792-102-5392/Differences%20Between%20Quest%20Code%20Tester%20for%20Oracle%20Freeware%20and%20Commercial.htm">very limited</a>.</li>
<li>It is a graphical tool &#8211; it can help you with quick creation of simple tests but when you will need more complex logic you might get stuck that you cannot do it (or you need to do it again in plain PL/SQL and have the same issues as in utPLSQL).</li>
<li>It stores tests in database repository &#8211; and it means that it might be hard to maintain unit tests in version control system like Subversion or Git.</li>
</ul>
<p>And finally also Oracle started to do something in PL/SQL unit testing area and there is unit testing support in latest <a href="http://www.oracle.com/technology/products/database/sql_developer/index.html">SQL Developer version 2.1</a> which currently still is in early adopter status. SQL Developer has very similar approach to Quest Code Tester &#8211; it is graphical tool which stores tests and test results in repository. So the benefit of SQL Developer over Quest Code Tester is that it is free <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  But compared to Quest Code Tester it still has less features (e.g. currently not all complex data types are supported) and still is not released as final version and still has bugs.</p>
<h3>Ruby as testing tool for PL/SQL</h3>
<p>As you probably know I am quite big <a href="http://www.ruby-lang.org/en/">Ruby</a> fan and always exploring new ways how to use Ruby to increase my productivity. And Ruby community has very high testing culture and has many good tools for testing support (I like and use <a href="http://rspec.info/">RSpec</a> testing framework). Therefore some time ago I started to use Ruby and RSpec also for testing PL/SQL code in our projects where we use Ruby on Rails on top of Oracle databases with existing PL/SQL business logic.</p>
<p>I have created <a href="http://github.com/rsim/ruby-plsql">ruby-plsql</a> library which provides very easy API for calling PL/SQL procedures from Ruby and recent ruby-plsql version <a href="http://blog.rayapps.com/2009/11/25/more-oracle-data-types-supported-by-ruby-plsql-gem/">supports majority of PL/SQL data types</a>.</p>
<p>So let&#8217;s start with with simple example how to use Ruby, RSpec and ruby-plsql to create PL/SQL procedure unit test. I will use BETWNSTR procedure example from utPLSQL examples:</p>
<pre>
CREATE OR REPLACE FUNCTION betwnstr (
   string_in   IN   VARCHAR2,
   start_in    IN   INTEGER,
   end_in      IN   INTEGER
)
   RETURN VARCHAR2
IS
   l_start PLS_INTEGER := start_in;
BEGIN
   IF l_start = 0
   THEN
      l_start := 1;
   END IF;
   RETURN (SUBSTR (string_in, l_start, end_in - l_start + 1));
END;
</pre>
<p>I took <a href="http://utplsql.cvs.sourceforge.net/viewvc/utplsql/examples/ut_betwnstr_gen.pkg?view=markup">example tests from utPLSQL</a> and wrote them in Ruby and RSpec:</p>
<pre>
describe "Between string" do
  it "should be correct in normal case" do
    plsql.betwnstr('abcdefg', 2, 5).should == 'bcde'
  end
  it "should be correct with zero start value" do
    plsql.betwnstr('abcdefg', 0, 5).should == 'abcde'
  end
  it "should be correct with way big end value" do
    plsql.betwnstr('abcdefg', 5, 500).should == 'efg'
  end
  it "should be correct with NULL string" do
    plsql.betwnstr(nil, 5, 500).should be_nil
  end
end
</pre>
<p>As you can see the tests are much shorter than in utPLSQL and are much more readable (also more readable than <a href="http://utplsql.cvs.sourceforge.net/viewvc/utplsql/examples/bewtnstr.utc?view=markup">utPLSQL template</a> which can be used to generate utPLSQL tests). And also you can create these tests faster than using GUI tools like Quest Code Tester or SQL Developer.</p>
<h3>More complex example</h3>
<p>Second more complex example I took from <a href="http://www.oracle.com/technology/obe/11gr2_db_prod/appdev/sqldev/sqldev_unit_test/sqldev_unit_test_otn.htm">SQL Developer unit testing tutorial</a>. We will create tests for PL/SQL procedure AWARD_BONUS:</p>
<pre>
CREATE OR REPLACE
 PROCEDURE award_bonus (
  emp_id NUMBER, sales_amt NUMBER) AS
  commission    REAL;
  comm_missing  EXCEPTION;
BEGIN
  SELECT commission_pct INTO commission
    FROM employees2
      WHERE employee_id = emp_id;
  IF commission IS NULL THEN
    RAISE comm_missing;
  ELSE
    UPDATE employees2
      SET salary = NVL(salary,0) + sales_amt*commission
        WHERE employee_id = emp_id;
  END IF;
END award_bonus;
</pre>
<p>I didn&#8217;t quite like the testing approach in SQL Developer unit testing tutorial &#8211; it was assuming that there is already specific data in employees2 table and was testing procedure using specific primary key values. As a result tests are not very readable as you cannot see all input data in the test case and tests could easily broke if initial data in table are different.</p>
<p>Therefore I created tests in Ruby using better approach that each test creates all necessary data that are needed for it and at the end of test there are no side effects which can influence other tests:</p>
<pre>
describe "Award bonus" do
  include CustomerFactory

  [ [1000,  1234.55,  0.10,   1123.46],
    [nil,   1234.56,  0.10,   123.46],
    [1000,  1234.54,  0.10,   1123.45]
  ].each do &#124;salary, sales_amt, commission_pct, result&#124;
    it "should calculate base salary #{salary.inspect} + sales amount #{sales_amt} * commission percentage #{commission_pct} = salary #{result.inspect}" do
      employee = create_employee(
        :commission_pct =&#62; commission_pct,
        :salary =&#62; salary
      )
      plsql.award_bonus(employee[:employee_id], sales_amt)
      get_employee(employee[:employee_id])[:salary].should == result
    end
  end
end
</pre>
<p>I am generating three different tests with three different sets of input values. When you run these tests you see result:</p>
<pre>
Award bonus
- should calculate base salary 1000 + sales amount 1234.55 * commission percentage 0.1 = salary 1123.46
- should calculate base salary NULL + sales amount 1234.56 * commission percentage 0.1 = salary 123.46
- should calculate base salary 1000 + sales amount 1234.54 * commission percentage 0.1 = salary 1123.45
</pre>
<p>In addition I am using factory pattern (create_customer method) for test data creation. When using factory pattern you create test data creation method which will create valid new record with default field values. If in your test you need some specific non-default values then you can pass just these values as parameters to factory method. Factory pattern also helps in the maintenance of tests. For example, if new mandatory columns will be added to employees table then it will be necessary to add new fields with default values in factory methods and nothing should be changed in individual tests.</p>
<p>Here is example of employee factory implementation:</p>
<pre>
module EmployeeFactory
  # Creates new employee with valid field values.
  # Pass in parameters only field values that you want to override.
  def create_employee(params)
    employee = {
      :employee_id =&#62; plsql.employees2_seq.nextval,
      :last_name =&#62; 'Last',
      :email =&#62; 'last@example.com',
      :hire_date =&#62; Date.today,
      :job_id =&#62; plsql.jobs.first[:job_id],
      :commission_pct =&#62; nil,
      :salary =&#62; nil
    }.merge(params)
    plsql.employees2.insert employee
    get_employee employee[:employee_id]
  end

  # Select employee by primary key
  def get_employee(employee_id)
    plsql.employees2.first :employee_id =&#62; employee_id
  end
end
</pre>
<p>And here is additional test for testing if procedure will raise exception if one input value is missing:</p>
<pre>
  it "should raise ORA-06510 exception if commission percentage is missing" do
    salary, sales_amt, commission_pct = 1000,  1234.55,  nil
    employee = create_employee(
      :commission_pct =&#62; commission_pct,
      :salary =&#62; salary
    )
    lambda do
      plsql.award_bonus(employee[:employee_id], sales_amt)
    end.should raise_error(Exception, /ORA-06510/)
  end
</pre>
<h3>How to use it</h3>
<p>I hope that if you are looking for PL/SQL unit testing tool then you will try this out <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  You can get examples from this article together with necessary setup code and installation instructions at  <a href="http://github.com/rsim/plsql-testing-examples">http://github.com/rsim/plsql-testing-examples</a>.</p>
<p>If you have any feedback or questions or feature suggestions then please comment.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[PLSQL Oracle Stored Function]]></title>
<link>http://rhde.wordpress.com/2009/11/26/plsql-oracle-stored-function/</link>
<pubDate>Thu, 26 Nov 2009 13:46:14 +0000</pubDate>
<dc:creator>rhde</dc:creator>
<guid>http://rhde.wordpress.com/2009/11/26/plsql-oracle-stored-function/</guid>
<description><![CDATA[Create Function create or replace function fu_add(p_in in number) return number as v_out number; beg]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><b>Create Function</b></p>
<pre>
create or replace function fu_add(p_in in number)
  return number
as
  v_out number;
begin
  v_out := p_in + 1;
  return v_out;
end;
</pre>
<pre>
exec dbms_output.put_line(fu_add(10));
</pre>
<pre>
select fu_add(10) from dual;
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[PLSQL Oracle Stored Procedure]]></title>
<link>http://rhde.wordpress.com/2009/11/26/plsql-oracle-stored-procedure/</link>
<pubDate>Thu, 26 Nov 2009 13:03:23 +0000</pubDate>
<dc:creator>rhde</dc:creator>
<guid>http://rhde.wordpress.com/2009/11/26/plsql-oracle-stored-procedure/</guid>
<description><![CDATA[Create Procedure Zum Anlegen oder Ändern einer Procedure wird das Recht &#8220;CREATE PROCEDURE]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><strong>Create Procedure</strong></p>
<p>Zum Anlegen oder Ändern einer Procedure wird das Recht &#8220;CREATE PROCEDURE&#8221; benötigt.</p>
<p>Anlegen:</p>
<pre>
create or replace procedure proc_ascii
as
  type t_ascii is varray(256) of char(1);
  a_ascii t_ascii;
begin null;
  a_ascii := t_ascii();
  a_ascii.extend(256);
  for i in 1 .. a_ascii.limit-1 loop
    a_ascii(i) := chr(i-1);
    dbms_output.put_line(i &#124;&#124; ' ' &#124;&#124; chr(i-1));
  end loop;
end;
</pre>
<p><strong>Drop Procedure</strong></p>
<p>Das Löschen einer Procedure erfolgt mit &#8220;DROP PROCEDURE -name-&#8221;.</p>
<p><strong>Aufruf Procedure</strong></p>
<p>Ausführen (1):</p>
<pre>exec proc_acsii</pre>
<p>Ausführen (2):</p>
<pre>begin proc_acsii;
end;</pre>
<p><strong>Kompilerfehler</strong></p>
<p>Wenn eine Fehlermeldung beim Anlegen kommt kann mit &#8220;show errors&#8221; die Meldung angezeigt werden.</p>
<p><strong>Parameter</strong></p>
<p>Parameter können innerhalb der Procedure nur lesend verwendet werden.</p>
<pre>
create or replace procedure proc_ascii(p_bis in number default 256)
as
  type t_ascii is table of char(1);
  a_ascii t_ascii;
begin null;
  a_ascii := t_ascii();
  a_ascii.extend(p_bis);
  for i in 1 .. p_bis loop
    a_ascii(i) := chr(i-1);
    dbms_output.put_line(i &#124;&#124; ' ' &#124;&#124; chr(i-1));
  end loop;
end;
</pre>
<p><b>Rückgaben</b></p>
<pre>
create or replace procedure proc_add(p_in in number, p_out out number)
as
begin null;
  p_out := p_in + 1;
end;
</pre>
<pre>
declare
  v_out number;
begin
  proc_add(10,v_out);
  dbms_output.put_line(v_out); /* 11 */
end;
</pre>
<pre>
declare
  v_out number;
begin
  proc_add(p_out=&#62;v_out,p_in=&#62;10);
  dbms_output.put_line(v_out); /* 11 */
end;
</pre>
<p>By-Reference:</p>
<pre>
create or replace procedure proc_add(p_inout in out number)
as
begin null;
  p_inout := p_inout + 1;
end;
</pre>
<pre>
declare
  v_inout number;
begin
  v_inout := 10;
  proc_add(v_inout);
  dbms_output.put_line(v_inout); /* 11 */
end;
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[PLSQL Oracle Tabelle mit Bulk Insert aus Array einfügen]]></title>
<link>http://rhde.wordpress.com/2009/11/26/plsql-oracle-tabelle-mit-bulk-insert-aus-array-einfugen/</link>
<pubDate>Thu, 26 Nov 2009 11:18:22 +0000</pubDate>
<dc:creator>rhde</dc:creator>
<guid>http://rhde.wordpress.com/2009/11/26/plsql-oracle-tabelle-mit-bulk-insert-aus-array-einfugen/</guid>
<description><![CDATA[PLSQL um in Oracle mehrere Zeilen &#8220;gleichzeitig&#8221; einzufügen: declare type t_emp is table]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>PLSQL um in Oracle mehrere Zeilen &#8220;gleichzeitig&#8221; einzufügen:</p>
<pre>
declare
  type t_emp is table of emp%rowtype;
  a_emp t_emp;
begin
  select * bulk collect into a_emp from emp;
  dbms_output.put_line('emp.count ' &#124;&#124; a_emp.count);
  -- Datensätze clonen
  for i in a_emp.first .. a_emp.last loop
    a_emp(i).empno := a_emp(i).empno + 1000;
    dbms_output.put_line('empno ' &#124;&#124; a_emp(i).empno);
  end loop;
  -- Bulk insert
  forall i in a_emp.first .. a_emp.last
    insert into emp values a_emp(i);
end;
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[PLSQL Oracle Tabelle mit Bulk Collect in Array einlesen ]]></title>
<link>http://rhde.wordpress.com/2009/11/26/plsql-oracle-tabelle-mit-bulk-collect-in-array-einlesen/</link>
<pubDate>Thu, 26 Nov 2009 11:02:59 +0000</pubDate>
<dc:creator>rhde</dc:creator>
<guid>http://rhde.wordpress.com/2009/11/26/plsql-oracle-tabelle-mit-bulk-collect-in-array-einlesen/</guid>
<description><![CDATA[Mit PLSQL eine komplette Oracle Tabelle in ein Array einlesen: declare type t_emp is table of emp%ro]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Mit PLSQL eine komplette Oracle Tabelle in ein Array einlesen:</p>
<pre>
declare
  type t_emp is table of emp%rowtype;
  a_emp t_emp;
begin
  select * bulk collect into a_emp from emp;
  dbms_output.put_line('emp.count ' &#124;&#124; a_emp.count);
  for i in a_emp.first .. a_emp.last loop
    dbms_output.put_line('empno ' &#124;&#124; a_emp(i).empno);
  end loop;
end;
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Mit PLSQL den Oracle Katalog nach Tabellen zu Spalten durchsuchen]]></title>
<link>http://rhde.wordpress.com/2009/11/26/mit-plsql-den-oracle-katalog-nach-tabellen-zu-spalten-durchsuchen/</link>
<pubDate>Thu, 26 Nov 2009 10:48:14 +0000</pubDate>
<dc:creator>rhde</dc:creator>
<guid>http://rhde.wordpress.com/2009/11/26/mit-plsql-den-oracle-katalog-nach-tabellen-zu-spalten-durchsuchen/</guid>
<description><![CDATA[PLSQL-Code für SQL*Plus oder SQL Developer declare v_count number; v_owner all_tab_columns.owner%typ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><strong>PLSQL-Code für SQL*Plus oder SQL Developer</strong></p>
<pre><font size="-2">
declare
  v_count number;
  v_owner all_tab_columns.owner%type;
  v_table_name all_tab_columns.table_name%type;
  v_column_name all_tab_columns.column_name%type;
  cursor c_all_tab_columns is
    select distinct owner, table_name
    from all_tab_columns
    where upper(column_name) like upper(v_column_name)
  ;
begin
  v_column_name := '&#38;like_column_name';
  dbms_output.put_line('Suche Tabellen, die Spalte ' &#124;&#124; v_column_name &#124;&#124; ' verwenden');
  for r_all_tab_columns in c_all_tab_columns loop
    v_owner := r_all_tab_columns.owner;
    v_table_name := r_all_tab_columns.table_name;
    v_count := 0;
    begin
      execute immediate 'select count(*)
                         from ' &#124;&#124; v_owner &#124;&#124; '.' &#124;&#124; v_table_name &#124;&#124; '
                        ' into v_count;
    exception
      when others then
        case sqlcode
          when -1031 then
            dbms_output.put_line(rpad('ErrAccess',10,'.') &#124;&#124; ' ' &#124;&#124; v_owner &#124;&#124; '.' &#124;&#124; v_table_name &#124;&#124; ' (ORA' &#124;&#124; SQLCODE &#124;&#124; ')');
          else
            dbms_output.put_line(rpad('ErrOthers',10,'.') &#124;&#124; ' ' &#124;&#124; v_owner &#124;&#124; '.' &#124;&#124; v_table_name &#124;&#124; ' (' &#124;&#124; SQLERRM &#124;&#124; ')');
        end case;
    end;
    if v_count &#62; 0 then
      dbms_output.put_line(lpad(v_count,10,'.') &#124;&#124; ' ' &#124;&#124; v_owner &#124;&#124; '.' &#124;&#124; v_table_name);
    end if;
  end loop;
end;
</font></pre>
<p><b>COLUMN_NAME LIKE &#8216;%TABLE_NAME%&#8217;</b></p>
<pre>
........29 OLAPSYS.ALL$OLAP_COLUMNS
.........1 OLAPSYS.ALL$OLAP_FOREIGN_KEYS
.........2 OLAPSYS.ALL$OLAP_KEYS
.........3 OLAPSYS.ALL$OLAP_KEY_COLUMN_USES
.........9 OLAPSYS.ALL$OLAP_TABLES
........97 SYS.ALL_ALL_TABLES
.....21690 SYS.ALL_CATALOG
.....15195 SYS.ALL_COL_COMMENTS
.......339 SYS.ALL_CONSTRAINTS
.......249 SYS.ALL_CONS_COLUMNS
........74 SYS.ALL_INDEXES
.......120 SYS.ALL_IND_COLUMNS
.........2 SYS.ALL_IND_STATISTICS
.......299 SYS.ALL_LOBS
........16 SYS.ALL_OBJECT_TABLES
.......565 SYS.ALL_OBJ_COLATTRS
........50 SYS.ALL_REFS
........17 SYS.ALL_STREAMS_UNSUPPORTED
.....20089 SYS.ALL_SYNONYMS
........81 SYS.ALL_TABLES
.....16139 SYS.ALL_TAB_COLS
.....15195 SYS.ALL_TAB_COLUMNS
.......266 SYS.ALL_TAB_COL_STATISTICS
......1611 SYS.ALL_TAB_COMMENTS
......3573 SYS.ALL_TAB_HISTOGRAMS
.........1 SYS.ALL_TAB_MODIFICATIONS
.....21100 SYS.ALL_TAB_PRIVS
.....21100 SYS.ALL_TAB_PRIVS_RECD
........85 SYS.ALL_TAB_STATISTICS
........32 SYS.ALL_TRIGGERS
.....15195 SYS.ALL_UPDATABLE_COLUMNS
.......283 SYS.ALL_VARRAYS
........15 SYS.ALL_XML_TABLES
.........2 SYS.ALL_XML_TAB_COLS
.......657 SYS.DICTIONARY
.....15702 SYS.DICT_COLUMNS
ErrAccess. SYS.FLASHBACK_TRANSACTION_QUERY (ORA-1031)
.......299 SYS.IMP_LOB_INFO
.....16139 SYS.LOADER_COL_FLAGS
......1055 SYS.LOADER_COL_TYPE
.......339 SYS.LOADER_CONSTRAINT_INFO
.......627 SYS.LOADER_FULL_ATTR_NAME
.....16139 SYS.LOADER_INTCOL_INFO
.......299 SYS.LOADER_LOB_FLAGS
.......120 SYS.LOADER_OID_INFO
........16 SYS.LOADER_REF_INFO
........32 SYS.LOADER_TRIGGER_INFO
.....20740 SYS.TABLE_PRIVILEGES
.........5 SYS.USER_ALL_TABLES
.........9 SYS.USER_CATALOG
........29 SYS.USER_COL_COMMENTS
.........3 SYS.USER_CONSTRAINTS
.........3 SYS.USER_CONS_COLUMNS
.........2 SYS.USER_INDEXES
.........2 SYS.USER_IND_COLUMNS
.........2 SYS.USER_IND_STATISTICS
.........5 SYS.USER_TABLES
........29 SYS.USER_TAB_COLS
........29 SYS.USER_TAB_COLUMNS
.........9 SYS.USER_TAB_COMMENTS
.........1 SYS.USER_TAB_MODIFICATIONS
.........9 SYS.USER_TAB_STATISTICS
........29 SYS.USER_UPDATABLE_COLUMNS
........17 SYS.USER_XML_COLUMN_NAMES
ErrOthers. SYS._ALL_FILE_GROUP_TABLES (ORA-00911: Ungültiges Zeichen)
ErrOthers. SYS._ALL_REPPARAMETER_COLUMN (ORA-00911: Ungültiges Zeichen)
</pre>
<p><b>COLUMN_NAME LIKE &#8216;%USER%&#8217;</b></p>
<pre>
........97 SYS.ALL_ALL_TABLES
.........2 SYS.ALL_DEQUEUE_QUEUES
........74 SYS.ALL_INDEXES
.........2 SYS.ALL_IND_STATISTICS
........16 SYS.ALL_OBJECT_TABLES
.........2 SYS.ALL_QUEUES
.........2 SYS.ALL_QUEUE_TABLES
........81 SYS.ALL_TABLES
.....16139 SYS.ALL_TAB_COLS
.....15195 SYS.ALL_TAB_COLUMNS
.......266 SYS.ALL_TAB_COL_STATISTICS
........85 SYS.ALL_TAB_STATISTICS
........22 SYS.ALL_USERS
.........1 SYS.EXU8USRU
ErrAccess. SYS.FLASHBACK_TRANSACTION_QUERY (ORA-1031)
.........1 SYS.GV_$AW_SESSION_INFO
.........1 SYS.IMP9USR
........30 SYS.KU$_PROCACT_SCHEMA_VIEW
.........8 SYS.KU$_SCHEMA_CALLOUT_VIEW
.........5 SYS.USER_ALL_TABLES
.........2 SYS.USER_INDEXES
.........2 SYS.USER_IND_STATISTICS
.........2 SYS.USER_ROLE_PRIVS
.........1 SYS.USER_SYS_PRIVS
.........5 SYS.USER_TABLES
........29 SYS.USER_TAB_COLS
........29 SYS.USER_TAB_COLUMNS
.........9 SYS.USER_TAB_STATISTICS
.........1 SYS.USER_USERS
.........1 SYS.V_$AW_SESSION_INFO
........28 SYS.V_$SESSION_CONNECT_INFO
.........1 WMSYS.ALL_WORKSPACES
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[More Oracle data types supported by ruby-plsql gem]]></title>
<link>http://blog.rayapps.com/2009/11/25/more-oracle-data-types-supported-by-ruby-plsql-gem/</link>
<pubDate>Wed, 25 Nov 2009 14:34:33 +0000</pubDate>
<dc:creator>Raimonds Simanovskis</dc:creator>
<guid>http://blog.rayapps.com/2009/11/25/more-oracle-data-types-supported-by-ruby-plsql-gem/</guid>
<description><![CDATA[I have just released ruby-plsql gem version 0.4.0 which provides many new features. You can read abo]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I have just released <a href="http://github.com/rsim/ruby-plsql">ruby-plsql</a> gem version 0.4.0 which provides many new features. You can read about initial versions of ruby-plsql in <a href="http://blog.rayapps.com/category/plsql/">previous blog posts</a>.</p>
<h3>Oracle complex data type support</h3>
<p>Initial versions of ruby-plsql supported just simple Oracle types like NUMBER, VARCHAR2, DATE, TIMESTAMP, CLOB, BLOB as PL/SQL procedure parameters. Now support for many more complex data types is added. See examples below how to call PL/SQL procedures with these complex data types.</p>
<h4>PL/SQL Record</h4>
<p>Let&#8217;s assume you have PL/SQL procedure with PL/SQL record type parameter (which most typically will be in table%ROWTYPE format):</p>
<pre>
CREATE TABLE test_employees (
          employee_id   NUMBER(15),
          first_name    VARCHAR2(50),
          last_name     VARCHAR2(50),
          hire_date     DATE
        );
CREATE OR REPLACE FUNCTION test_full_name (p_employee test_employees%ROWTYPE)
RETURN VARCHAR2 IS
BEGIN
  RETURN p_employee.first_name &#124;&#124; ' ' &#124;&#124; p_employee.last_name;
END;
</pre>
<p>Then you can create Ruby Hash with record field values (specifying field names as Symbols), e.g.:</p>
<pre>
p_employee = {
  :employee_id =&#62; 1,
  :first_name =&#62; 'First',
  :last_name =&#62; 'Last',
  :hire_date =&#62; Time.local(2000,01,31)
}
</pre>
<p>and pass this Hash as a parameter which will be translated to PL/SQL record parameter by ruby-plsql:</p>
<pre>
plsql.test_full_name(p_employee) #=&#62; "First Last"
# or
plsql.test_full_name(:p_employee =&#62; p_employee) #=&#62; "First Last"
</pre>
<p>In the same way you can get PL/SQL function return values or output parameter values as Hash values.</p>
<h4>Object type</h4>
<p>In similar way also object type parameters can be passed as Hash values. In this case also nested objects or nested collections of objects are supported:</p>
<pre>
CREATE OR REPLACE TYPE t_address AS OBJECT (
  street    VARCHAR2(50),
  city      VARCHAR2(50),
  country   VARCHAR2(50)
);
CREATE OR REPLACE TYPE t_phone AS OBJECT (
  type            VARCHAR2(10),
  phone_number    VARCHAR2(50)
);
CREATE OR REPLACE TYPE t_phones AS TABLE OF T_PHONE;
CREATE OR REPLACE TYPE t_employee AS OBJECT (
  employee_id   NUMBER(15),
  first_name    VARCHAR2(50),
  last_name     VARCHAR2(50),
  hire_date     DATE,
  address       t_address,
  phones        t_phones
);
CREATE OR REPLACE FUNCTION test_full_name (p_employee t_employee)
  RETURN VARCHAR2
IS
BEGIN
  RETURN p_employee.first_name &#124;&#124; ' ' &#124;&#124; p_employee.last_name;
END;
</pre>
<p>and from Ruby side you can call this PL/SQL function as:</p>
<pre>
p_employee = {
  :employee_id =&#62; 1,
  :first_name =&#62; 'First',
  :last_name =&#62; 'Last',
  :hire_date =&#62; Time.local(2000,01,31),
  :address =&#62; {:street =&#62; 'Main street 1', :city =&#62; 'Riga', :country =&#62; 'Latvia'},
  :phones =&#62; [{:type =&#62; 'mobile', :phone_number =&#62; '123456'}, {:type =&#62; 'home', :phone_number =&#62; '654321'}]
}
plsql.test_full_name(p_employee) #=&#62; "First Last"
# or
plsql.test_full_name(:p_employee =&#62; p_employee) #=&#62; "First Last"
</pre>
<p>And also object type return values and output parameters will be returned as Ruby Hash values (with nested Hashes or Arrays if necessary).</p>
<p>There is one limitation that these object types should be defined as database types and not just inside PL/SQL package definition. Unfortunately you cannot access type definitions inside packages from OCI or JDBC drivers and as a result cannot call such procedures from outside of PL/SQL.</p>
<h4>TABLE and VARRAY collections</h4>
<p>TABLE and VARRAY collection parameters can be passed as Array values:</p>
<pre>
CREATE OR REPLACE TYPE t_numbers AS TABLE OF NUMBER(15);
CREATE OR REPLACE FUNCTION test_sum (p_numbers IN t_numbers)
  RETURN NUMBER
IS
  l_sum   NUMBER(15) := 0;
BEGIN
  IF p_numbers.COUNT &#62; 0 THEN
    FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
      IF p_numbers.EXISTS(i) THEN
        l_sum := l_sum + p_numbers(i);
      END IF;
    END LOOP;
    RETURN l_sum;
  ELSE
    RETURN NULL;
  END IF;
END;
</pre>
<p>And from Ruby side:</p>
<pre>
plsql.test_sum([1,2,3,4]) #=&#62; 10
</pre>
<h4>CURSOR</h4>
<p>You can get also cursor return values from PL/SQL procedures:</p>
<pre>
CREATE OR REPLACE FUNCTION test_cursor
  RETURN SYS_REFCURSOR
IS
  l_cursor  SYS_REFCURSOR;
BEGIN
  OPEN l_cursor FOR
  SELECT * FROM test_employees ORDER BY employee_id;
  RETURN l_cursor;
END;
</pre>
<p>can be called from Ruby in the following way:</p>
<pre>
plsql.test_cursor do &#124;cursor&#124;
  cursor.fetch #=&#62; first row from test_employees will be returned
end
</pre>
<p>It is important to pass block parameter in this case and do something with returned cursor within this block as after ruby-plsql finishes PL/SQL procedure call it will close all open cursors and therefore it will not be possible to do anything with returned cursor outside this block.</p>
<p>It is also possible to use returned cursor as input parameter for another PL/SQL procedure:</p>
<pre>
CREATE OR REPLACE FUNCTION test_cursor_fetch(p_cursor SYS_REFCURSOR)
  RETURN test_employees%ROWTYPE
IS
  l_record  test_employees%ROWTYPE;
BEGIN
  FETCH p_cursor INTO l_record;
  RETURN l_record;
END;
</pre>
<pre>
plsql.test_cursor do &#124;cursor&#124;
  plsql.test_cursor_fetch(cursor) #=&#62; first record as Hash
end
</pre>
<p><strong>Note</strong>: you can pass cursors as PL/SQL procedure input parameter just when using ruby-plsql on MRI 1.8/1.9 with ruby-oci8, unfortunately I have not found a way how to pass cursor as input parameter when using JRuby and JDBC.</p>
<h4>BOOLEAN</h4>
<p>And finally you can use also PL/SQL BOOLEAN type &#8211; it is quite tricky data type as it is supported just by PL/SQL but not supported as data type in Oracle tables. But now you can also use it with ruby-plsql:</p>
<pre>
CREATE OR REPLACE FUNCTION test_boolean
  ( p_boolean BOOLEAN )
  RETURN BOOLEAN
IS
BEGIN
  RETURN p_boolean;
END;
</pre>
<pre>
plsql.test_boolean(true) #=&#62; true
</pre>
<p>You can find more PL/SQL procedure call usage examples in <a href="http://github.com/rsim/ruby-plsql/blob/master/spec/plsql/procedure_spec.rb">ruby-plsql RSpec tests</a>.</p>
<h3>Table and sequence operations</h3>
<p>I have been using and promoting to others ruby-plsql as PL/SQL procedure unit testing tool. As current PL/SQL unit testing tools are not so advanced and easy to use as Ruby unit testing tools then I like better to use Ruby testing tools (like RSpec) together with ruby-plsql to write short and easy to understand PL/SQL unit tests.</p>
<p>In unit tests in setup and teardown methods you typically need some easy way how to create some sample data in necessary tables as well as to validate resulting data in tables after test execution.</p>
<p>If you are Ruby on Rails developer then you probably will use ActiveRecord (or DataMapper) for manipulation of table data. But if Ruby is used just for unit tests then probably ActiveRecord would be too complicated for this task.</p>
<p>Therefore I added some basic table operations to ruby-plsql which might be useful e.g. in unit tests. Some syntax ideas for these table operations are coming from <a href="http://github.com/jeremyevans/sequel/">Sequel</a> Ruby library.</p>
<h4>INSERT</h4>
<pre>
# insert one record
employee = { :employee_id =&#62; 1, :first_name =&#62; 'First', :last_name =&#62; 'Last', :hire_date =&#62; Time.local(2000,01,31) }
plsql.employees.insert employee # INSERT INTO employees VALUES (1, 'First', 'Last', ...)
</pre>
<pre>
# insert many records
employees = [employee1, employee2, ... ]  # array of many Hashes
plsql.employees.insert employees
</pre>
<p>If primary key values should be selected from sequence then you can get next sequence values with</p>
<pre>
plsql.employees_seq.nextval # SELECT employees_seq.NEXTVAL FROM dual
plsql.employees_seq.currval # SELECT employees_seq.CURRVAL FROM dual
</pre>
<h4>SELECT</h4>
<pre>
# select one record
plsql.employees.first # SELECT * FROM employees
                      # fetch first row =&#62; {:employee_id =&#62; ..., :first_name =&#62; '...', ...}
plsql.employees.first(:employee_id =&#62; 1)  # SELECT * FROM employees WHERE employee_id = 1
plsql.employees.first("WHERE employee_id = 1")
plsql.employees.first("WHERE employee_id = :employee_id", 1)
# select many records
plsql.employees.all                       # =&#62; [{...}, {...}, ...]
plsql.employees.all(:order_by =&#62; :employee_id)
plsql.employees.all("WHERE employee_id &#62; :employee_id", 5)
</pre>
<pre>
# count records
plsql.employees.count                     # SELECT COUNT(*) FROM employees
plsql.employees.count("WHERE employee_id &#62; :employee_id", 5)
</pre>
<h4>UPDATE</h4>
<pre>
# update records
plsql.employees.update(:first_name =&#62; 'Second', :where =&#62; {:employee_id =&#62; 1})
                      # UPDATE employees SET first_name = 'Second' WHERE employee_id = 1
</pre>
<h4>DELETE</h4>
<pre>
# delete records
plsql.employees.delete(:employee_id =&#62; 1) # DELETE FROM employees WHERE employee_id = 1
</pre>
<h4>Other SQL statements</h4>
<p>Any other SELECT statement can be executed with</p>
<pre>
plsql.select :first, "SELECT ..."
# or
plsql.select :all, "SELECT ..."
</pre>
<p>or any other non-SELECT SQL statement can be executed with</p>
<pre>
plsql.execute "..."
</pre>
<p>And also COMMIT or ROLLBACK could be executed simply with</p>
<pre>
plsql.commit
plsql.rollback
</pre>
<p>I plan to write a separate blog post about how I recommend to create PL/SQL unit tests using Ruby and ruby-plsql and RSpec.</p>
<h3>Install</h3>
<p>As always you can install latest version of ruby-plsql with</p>
<pre>
gem install ruby-plsql
</pre>
<p>Latest gem version is just on <a href="http://gemcutter.org/gems/ruby-plsql">Gemcutter</a> but now it should be available as default gem source for all Ruby installations.</p>
<p>And as always ruby-plsql is supported both on</p>
<ul>
<li>Ruby 1.8.6/1.8.7 or Ruby 1.9.1 with ruby-oci8 gem version 2.0.3 or later (some specific issues with complex data types will be fixed in later versions of ruby-oci8)</li>
<li>JRuby 1.3/1.4 with Oracle JDBC driver (testing mainly with ojdbc14.jar but also ojdbc5.jar or ojdbc6.jar should be fine)</li>
</ul>
<p>Please try it out and tell me if there are any issues with some particular data types or if there are still some unsupported PL/SQL data types that you would like to be supported in ruby-plsql. And also I encourage you to try ruby-plsql out for PL/SQL unit testing if you had no PL/SQL unit tests previously <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[rowcount and variable value on unsuccessful select.]]></title>
<link>http://akmanocha.wordpress.com/2009/11/25/rowcount-and-variable-value-on-unsuccessful-select/</link>
<pubDate>Wed, 25 Nov 2009 14:23:43 +0000</pubDate>
<dc:creator>akmanocha</dc:creator>
<guid>http://akmanocha.wordpress.com/2009/11/25/rowcount-and-variable-value-on-unsuccessful-select/</guid>
<description><![CDATA[Learn a new thing today, as always. That&#8217;s a classical hierarchical tree problem reprsented in]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Learn a new thing today, as always. That&#8217;s a classical hierarchical tree problem reprsented in relational database.</p>
<p>A table having nodeId and parentNodeId and thus the tree is set up. How do you get the org tree startting from anode going up till the root node level? A stored proc.</p>
<p>But two problems in the implementation.</p>
<p>1. If you want base your loop termination logic in a PL/SQL stored proc on the basis of rowcount on the select statement having where clause.  Then it doesn&#8217;t work. It is not considered unsuccessful, hence doesn&#8217;t result ZERO as rowcount as per PL/SQL rule.</p>
<p>2. If you want to have your loop termination logic on the basis of variable&#8217;s value obtained from the select. That too doesnt gonna work as it doesnt update the value with null on the basis of no row returend.</p>
<p>THE SOLUTION: have a prevParentNodeId and parentNodeId. Andrest you know. Check for the inequality/equality of those.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA["New" operators of PL/SQL]]></title>
<link>http://timurakhmadeev.wordpress.com/2009/11/25/new-operators-of-plsql/</link>
<pubDate>Tue, 24 Nov 2009 21:24:38 +0000</pubDate>
<dc:creator>Timur Akhmadeev</dc:creator>
<guid>http://timurakhmadeev.wordpress.com/2009/11/25/new-operators-of-plsql/</guid>
<description><![CDATA[New PL/SQL &#8220;operators&#8221; discovered by Elic @ SQL.ru SQL&gt; exec x := 1 2 BEGIN x := 1 2;]]></description>
<content:encoded><![CDATA[New PL/SQL &#8220;operators&#8221; discovered by Elic @ SQL.ru SQL&gt; exec x := 1 2 BEGIN x := 1 2;]]></content:encoded>
</item>
<item>
<title><![CDATA[PL/pgSQL – SQL Procedural Language]]></title>
<link>http://wirabumisoftware.wordpress.com/2009/11/22/plpgsql-%e2%80%93-sql-procedural-language/</link>
<pubDate>Sun, 22 Nov 2009 12:30:48 +0000</pubDate>
<dc:creator>wirabumisoftware</dc:creator>
<guid>http://wirabumisoftware.wordpress.com/2009/11/22/plpgsql-%e2%80%93-sql-procedural-language/</guid>
<description><![CDATA[Tulisan ini menguraikan apa dan bagaimana cara membuat function menggunakan PL/pgSQL. Didalamnya ter]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Tulisan ini menguraikan apa dan bagaimana cara membuat function menggunakan PL/pgSQL. Didalamnya terdapat panduan tahap demi tahap dalam membuat dan menggunakan function menggunakan PL/pgSQL. Setelah membaca tulisan ini, anda diharapkan dapat membuat dan menggunakan fungsi menggunakan PL/pgSQL.<br />
<!--more--><strong>Overview</strong><br />
PL/pgSQL adalah procedural language yang loadable (dapat langsung digunakan tanpa restart server) pada sistem database PostgreSQL. PL/pgSQL didesain dengan tujuan supaya kita dapat membuat sebuah procedural language yang:</p>
<ul>
<li> dapat dipakai untuk membuat function atau trigger</li>
<li> dapat menambahkan sruktur kontrol pada bahasa SQL</li>
<li> dapat melakukan komputasi kompleks</li>
<li> semua type, function, dan operator yang didefinisikan user (buatan anda sendiri atau orang lain) dapat diturunkan (inherit)</li>
<li> dapat dipercaya oleh server</li>
<li> mudah digunakan</li>
</ul>
<p>Function yang telah anda buat menggunakan PL/pgSQL dapat digunakan sebagaimana function bawaan yang sudah ada. Misalnya, anda dapat membuat fungsi komputasi kondisional yang kompleks, kemudian menggunakannya untuk membuat operator atau menggunakannya untuk membuat index.<br />
<strong></strong></p>
<p><strong>Keuntungan menggunakan PL/pgSQL</strong><br />
SQL merupakan bahasa yang digunakan PostgreSQL, dan begitu pula sebagian besar sistem database relasional (RDBMS: Relational Dtabase Management System) juga menggunakanSQL sebagai bahasa query. Bahasa ini begitu portable (dapat dipakai dimana saja, dan tentu ada sedikit perbedaan antar RDBMS) dan mudah dipelajari.<br />
Namun, setiap pernyataan SQL harus dijalankan secara terpisah oleh server database. Artinya, setiap aplikasi client anda harus mengirimkan setiap perintah SQL pada server satu per satu. Seletah mengirim 1 perintah SQL, client menunggu hasil prosesnya, kemudian menerima hasilnya dan memroses hasil tersebut. Client kemudian melakukan komputasi selanjutnya, dan kemudian mengirim pernyataan SQL berikutnya pada server. Begitu seterusnya. Hal ini tentu menimbulkan beban komunikasi antara server dan client, yang tentu akan menimbulkan beban jaringan, utamanya jika client dan server database anda terpisah.<br />
Dengan menggunakan PL/pgSQL anda dapat mengelompokkan sebuah blok komputasi atau serangkaian query langsung didalam server, yang tentu saja anda memanfaatkan keunggulan procedural language dan kemudahan penggunaan SQL, sekaligus menghemat ongkos komunikasi dan beban jaringan.<br />
beban komunikasi dari server ke client dan sebaliknya dihilangkan<br />
client tidak perlu menerima hasil/data pada saat proses berlangsung, cukup menerima hasil akhir dari proses tersebut, dan siap digunakan untuk proses komputasi berikutnya<br />
dapat mencegah pengiriman query dari client ke server berulang-ulang, karena function dijalankan di sisi server<br />
Hal ini tentu saja meningkatkan performa aplikasi anda secara signifikan. Dalam membuat function menggunakan PL/pgSQL, anda dapat menggunakan tipe data, operator, dan function pada SQL.<br />
<strong></strong></p>
<p><strong>Tipe data parameter dan hasil yang didukung<br />
</strong>Function yang dibuat dari PL/pgSQL dapat menerima parameter dalam bentuk skalar apa saja (integrer, char, float, dsb) maupun array yang didukung server, dan dapat pula mengembalikan nilai/hasil dengan tipe data tersebut. Function ini juga dapat menerima parameter dan mengembalikan nilai dengan tipe data komposit (tipe row). Function ini juga dapat mengembalikan nilai berupa record yang kolomnya sesuai dengan query yang dijalankan. Function yang dibuat dari PL/pgSQL juga dapat menerima parameter dan mengembalikan nilai bertipe polymorphic (anyelement, anyarray, dsb).<br />
Function dari PL/pgSQL juga dapat dideklarasikan untuk mengembalikan nilai berupa sebuah set atau tabel. Dengan demikian fungsi ini dapat memberikan hasil dengan menjalankan perintah RETURN NEXT untuk setiap elemen dalam 1 record hasil query, atau menggunakan RETURN QUERY untuk mendapatkan semua hasil query.<br />
Function ini juga dapat dideklarasikan untuk menghasilkan nilai void jika anda menghendaki function ini tidak mengembalikan apa-apa.<br />
Function ini juga memiliki kemampuan untuk menerima parameter dengan tipe data berupa output, sehingga anda tidak perlu memberi perintah secara eksplisit untuk mengembalikan sebuah nilai dari suatu function. Ini seringkali berguna jika anda ingin mengembalikan beberapa nilai sekaligus.<br />
Function Anda yang Pertama<br />
Pada bagian ini anda akan saya ajak untuk membuat function, tentu saja function anda yang pertama. Pertama anda harus memiliki software-software yang dibutuhkan. Jika anda meggunakan windows, ada cukup perlu master installer PostgreSQL yang didalamnya sudah memasukkan server PostgreSQL dan aplikasi (client) manajemen database PgAdmin. Jika anda menggunakan linux, gunakan server PostgreSQL dan PgAdmin sesuai dengan distribusi/distro yang anda gunakan. Saya menggunakan PostgreSQL 8.3 dan PgAdmin 1.8.<br />
Buatlah sebuah database untuk mempraktekkan contoh-contoh yang akan saya tampilkan. Buat database baru dengan nama contohplsql. Kemudian jalankan script SQL yang dapat di-download disini, pada database tersebut. Jika sukses, database contohplsql akan memiliki 3 tabel (nama, alamat, negara) dan 2 function (uuid_generate_v4, get_uuid). Kedua function ini hanya digunakan untuk meng-generate primary key pada tiap-tiap record menggunakan algoritma UUID. Klik disini untuk informasi lebih lanjut tentang UUID.<br />
Melalui PgAdmi, masuklah pada database contohplsql, kemudian buka window baru untuk menuliskan script SQL.<br />
[gambar 1]<br />
[gambar 2]<br />
Kemudian tuliskan kode berikut:<br />
<em>CREATE FUNCTION somefunc() RETURNS integer AS $$<br />
&#60;&#60; outerblock &#62;&#62;<br />
DECLARE<br />
quantity integer := 30;<br />
BEGIN<br />
RAISE NOTICE &#8216;Quantity here is %&#8217;, quantity;  &#8212; mencetak 30<br />
quantity := 50;</em></p>
<p><em>/* Create a subblock */</em></p>
<p><em>DECLARE<br />
quantity integer := 80;<br />
BEGIN<br />
RAISE NOTICE &#8216;Quantity here is %&#8217;, quantity;  &#8212; mencetak 80<br />
RAISE NOTICE &#8216;Outer quantity here is %&#8217;, outerblock.quantity;  &#8212; mencetak 50<br />
END;</em></p>
<p><em>RAISE NOTICE &#8216;Quantity here is %&#8217;, quantity;  &#8212; mencetak 50</em></p>
<p><em>RETURN quantity;<br />
END outerblock;<br />
$$ LANGUAGE plpgsql;<br />
</em></p>
<p>Jalankan kode tersebut, anda baru saja membuat function anda yang pertama, dengan nama somefunc. Kemudian panggillah function yang baru saja anda buat dengan menjalankan perintah berikut:<br />
<em>SELECT * FROM somefunc()<br />
</em>Maka anda akan mendapatkan hasil berupa return value bertipe integer bernilai 50. Selamat! Anda baru saja berhasil membuat function.<br />
Struktur PL/pgSQL<br />
PL/pgSQL merupakan bahasa yang dibangun dari blok-blok. Syntax lengkap untuk mendefinisikan sebuah function harus membentuk sebuah blok. Sebuah blok didefinisikan sebagai berikut:<br />
<em>[&#60;&#62;]<br />
[DECLARE<br />
declaration]<br />
BEGIN<br />
statement<br />
END [label];<br />
</em>Pada function pertama yang sudah anda buat tedapat blok yang bernama outerblock. Karena dia didefinisikan dibagian atas, blok ini melingkupi seluruh function. Didalam blok outerblock terdapat blok yang tidak diberi nama (jadi block sebenarnya ditandai dari adanya BEGIN dan END). Setiap deklarasi dan setiap statement dalam sebuah blok harus diakhiri dengan titik koma (;). Sebuah blok yang berada dalam blok lain, tanda titik koma harus ada setelah END. Khusus untuk blok yang menandakan badan function (mencakup keseluruhan isi function) tidak perlu titik koma.<br />
Label hanya diperlukan untuk menandai sebuah blok jika anda menggunakan statement EXIT, atau untuk menandai nama variable yang sifatnya lokal di dalam blok tersebut. Label yang diberikan harus cocok antara yang ada di bagian BEGIN dan END. Pada function contohplsql, block outerblock diakhiri dengan END outerblock;<br />
Semua kata kunci (key word) dibedakan huruf besar/kecil. Identifier secara implisit dikonvesi menjadi huruf kecil, kecuali yang telah diberi petik ganda, sama seperti SQL pada umumnya.<br />
Ada 2 cara untuk menuliskan komentar pada PL/pgSQL. Pertama menggunakan awalan double dash (&#8211;), kedua menggunakan awalan /* dan akhiran */.<br />
Setiap statement dalam sesi statement pada sebuah blok dapat ditempatkan pada sebuah sub-blok. Pembuatan sub-blok bisa didasarkan pada logika pemrograman maupun untuk tujuan melokalisir variable. Namun, anda masih bisa mengakses varible diluar blok dengan jalan menggunakan nama label blok tersebut. Perhatikan function pertama yang sudah anda buat. Blok bagian luar bernama outerblock, sedangkan didalam blok ini terdapat sub-blok yang tidak diberi nama. Pada contoh ini, sub-blok digunakna untuk melokalisir varible. Didalam sub-blok ini terdapat variable quantity, dimana namanya sama dengan variable pada blok induknya. Namun karena posisinya berbeda blok, kedua variable ini berbeda. Untuk mengakses variable quantity pada sub-blok cukup menggunakan quantity saja, sementara untuk quantity yang berada pada blok induk harus menggunakan outerblock.quantity.<br />
Catatan: Pada function pertama yang sudah anda buat sebenarnya tedapat blok diluar semua blok yang telah didefinisikan. Blok ini dibuat oleh server secara implisit dan mencakup semua bagian dari blok-blok yang telah anda buat. Blok ini memiliki nama yang sama dengan nama function. Jadi, sebenarnya pada blok inilah anda mendeklarasikan parameter function, begitu juga varible spesial lainnya seperti FOUND. Dengan demikian anda dapat mengakses nama parameter dan variable khusus lainnya menggunakan nama function ini.<br />
Penting untuk memahami dan tidak bingung akan penggunaan BEGIN/END sebagai blok dan sebagai transaction. Pada PL/pgSQL pernyataan BEGIN/END hanya digunakan untuk pengelompokan saja, dia tidak bisa start/commit sebuah transaction. Namun, sebuah blok yang didalamnya terdapat klausa EXCEPTION akan membentuk susunan blok tertentu dimana sebuah rangkaian statement didalamnya dapat di-roll back tanpa mempengaruhi perintah-perintah di blok lain.</p>
<p><strong>Declaration<br />
</strong>Semua variable yang digunakan dalam blok harus dideklarasikan dalam bagian deklarasi pada blok tersebut. (Kecuali varible yang digunakan dalam iterasi LOOP, yang akan dideklarasikan secara otomatis sebagai integer). PL/pgSQL dapat memiliki tipe variable sebagaimana yang dimiliki SQL, seperti integer, char, maupun varchar.<br />
Pada function somefunc dideklarasikan 1 variable bernama quantity pada outerblock, dan 1 variable bernama quantity pada sub-blok. Berikut adalah contoh deklarasi variable:<br />
<em>user_id integer;<br />
quantity numeric(5);<br />
url varchar;<br />
myrow tablename%ROWTYPE;<br />
myfield tablename.columnname%TYPE;<br />
arow RECORD;<br />
</em>Syntax umum untuk mendeklarasikan variable adalah sebagai berikut:<br />
<em>name [ CONSTANT ] type [ NOT NULL ] [ { DEFAULT &#124; := } expression ];</em><br />
Jika dalam deklarasi varible terdapat klausa DEFAULT, maka value awal akan dimasukkan ke dalam variable tersebut. Namun, jika tidak ada klausa DEFAULT, nilaia awal yang dimasukkan dalam variable tersebut adalah SQL NULL. Klausa CONSTANT membuat nilai variable ini selalu tetap, sehingga jika terjadi perintah pengisian nilai pada variable ini akan terjadi error. Klausa NOT NULL membuat pengisian SQL NULL pada variable ini error. Oleh karena itu, jika terdapat salah satu saja dari kedua properti ini, maka sebuah variable harus memiliki klausa DEFAULT. Khusus untuk klausa NOT NULL, nilai awal yang dimasukkan tidak boleh NULL.<br />
Klausa DEFAULT dijalankan setiap kali blok tersebut dijalankan, jadi tidak hanya saat function di-compile. Contoh, jika anda mendefinisikan varible bertipe DATE, kemudian diisi dengan nilai default NOW(), maka isi varible tersebut akan berubah setiap blok dijalankan, bukan hanya saat pertama kali function ini di-compile.<br />
Contoh penggunaan klausa DEFAULT dan CONSTANT:<br />
<em>quantity integer DEFAULT 32;<br />
url varchar := &#8216;http://mysite.com&#8217;;<br />
user_id CONSTANT integer := 10;<br />
</em></p>
<p><strong>Alias untuk Parameter Fungsi<br />
</strong>Alias digunakan untuk memberikan nama pada parameter fungsi. Secara default nama parameter adalah angka yang urut sesuai definisi paramter fungsi. Perhatikan contoh berikut:<br />
<em>CREATE FUNCTION somefunc(integer, varchar) RETURNS integer AS $$<br />
</em>Pada contoh diatas, terdapat 2 parameter pada function somefunc, keduanya berturut-turut bertipe integer dan varchar. Secara default kedua parameter tersebut berturut-turut bernama $1 dan $2. Penamaan semacam ini, pada kasus tertentu, menyulitkan anda dalam membuat dan membaca kode function. Untuk itu diperlukan penamaan parameter yang mencerminkan penggunaan parameter tersebut. Proses penamaan ini disebut dengan alias.<br />
Terdapat 2 cara membuat alias pada parameter function. Perhatikan 2 contoh berikut:<br />
<em>CREATE FUNCTION instr(varchar, integer) RETURNS integer AS $$<br />
DECLARE<br />
v_string ALIAS FOR $1;<br />
index ALIAS FOR $2;<br />
BEGIN<br />
&#8211; some computations using v_string and index here<br />
END;<br />
$$ LANGUAGE plpgsql;</em></p>
<p><em>CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$<br />
BEGIN<br />
tax := subtotal * 0.06;<br />
END;<br />
$$ LANGUAGE plpgsql<br />
</em>Pada contoh pertama, alias dilaksanakan pada bagian deklarasi function. Sedangkan pada contoh kedua, alias dilaksanakan saat pendefinisian parameter. Kedua contoh diatas tidak sepenuhnya identik. Pada contoh kedua, kita dapat membuat referensi sales_tax.subtotal, sedangkan pada contoh pertama fitur ini tidak ada. Hal ini disebabkan karena PL/pgSQL akan membuatkan label khusus secara implisit yang melingkup semua isi function dengan nama label sama dengan nama function, sehingga sales_tax.total nampak pada label ini, sedangkan pada contoh kedua alias parameter berada pada label yang berbeda.<br />
Pada kasus parameter dan return function yang bertipe polymorphic, PL/pgSQL akan secara otomatis membuat variable bernama $0 yang akan menjadi tipe data aktual dari return function tersebut. Ini dapat digunakan sebagai variable yang dapat menampung nilai return dari suatu function, meski kadang ini tidak diperlukan. Selanjutnya, variable ini dapat diberi alias seperti parameter, yang telah dijelaskan sebelumnya. Perhatikan contoh berikut:<br />
<em>CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement)<br />
RETURNS anyelement AS $$<br />
DECLARE<br />
result ALIAS FOR $0;<br />
BEGIN<br />
result := v1 + v2 + v3;<br />
RETURN result;<br />
END;<br />
$$ LANGUAGE plpgsql;</em></p>
<p><em>CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement,<br />
OUT sum anyelement)<br />
AS $$<br />
BEGIN<br />
sum := v1 + v2 + v3;<br />
END;<br />
$$ LANGUAGE plpgsql;<br />
</em>Pada contoh pertama, alias dilaksanakan pada bagian deklarasi function. Pada contoh kedua, alias dilaksanakan pada pendefinisian parameter.</p>
<p><strong>Menyalin Tipe Data<br />
</strong><em>variable%TYPE</em></p>
<p>Anda dapat mendefinisikan sebuah variable dengan tipe data yang dinamis, artinya tipe data variable tersebut dapat berubah saat function dijalankan (on the fly). Tipe data seperti ini banyak dibutuhkan jika anda ingin membuat variable yang menampung data dari sebuah kolom pada suatu tabel. %TYPE akan menyajikan tipe data atau tipe kolom pada sebuah tabel. Jika anda ingin membuat variable yang bernama user_id dan digunakan untuk menampung nilai kolom user_id pada tabel user, maka syntax yang digunakan adalah:<br />
<em>user_id user.user_id%TYPE;</em></p>
<p>Jika kolom user_id bertipe integer maka variable user_id juga beritipe integer. Jika dikemudian hari anda mengubah kolom ini sehingga bertipe float, maka variable user_id juga akan bertipe float, tanpa harus mengganti function ini.</p>
<p><strong>Row Type<br />
</strong><em>name tablename%ROWTYPE;<br />
name composite_type_name;</em></p>
<p>Sebuah variable komposit adalah variable row (atau variable row-type). Sebuah variable row dapat menampung nilai dari seluruh kolom hasil perintah select. Setiap kolom dapat diakses menggunakan tanda dot (.), misalnya: variablerow.namafield.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Cursor con parametro en PL/SQL]]></title>
<link>http://drocco.wordpress.com/2009/11/16/cursor-con-parametro-en-plsql/</link>
<pubDate>Mon, 16 Nov 2009 17:32:59 +0000</pubDate>
<dc:creator>Rocco</dc:creator>
<guid>http://drocco.wordpress.com/2009/11/16/cursor-con-parametro-en-plsql/</guid>
<description><![CDATA[En la etiqueta DECLARE colocamos el cursor y añadimos un parámetro, también agregamos la consulta sq]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>En la etiqueta DECLARE colocamos el cursor y añadimos un parámetro, también agregamos la consulta sql, la cual proporcionará el resultado que almacenará el cursor dependiendo del parámetro dado.</p>
<p>En la etiqueta BEGIN-END agregamos un ciclo que nos permitirá desplegar la información que contiene el cursor.</p>
<p>A continuación un ejemplo de una tabla regiones que tiene dos atributos reg_codigo, reg_nombre:</p>
<pre style="background:#F4F5F7;border:1px dashed #CCC;margin:5px 0;padding:5px 12px 5px 10px;"><code>DECLARE
   CURSOR cemp(r_codigo IN number) IS
   SELECT reg_codigo, reg_nombre
   FROM regiones
   WHERE reg_codigo = r_codigo;
   cepm_rec cemp%ROWTYPE;
   v_codigo number;
BEGIN
   v_codigo := codigo_region
   FOR cemp_rec IN cemp(v_codigo) LOOP
      :bloque1.mostrar_nombre := cemp_rec.reg_nombre;
   END LOOP;
END;</code></pre>
<p>El código está en Oracle Forms lo cual muestra por pantalla el item &#8220;:bloque1.mostrar_nombre&#8221; entregando el nombre de la región según codigo_region.</p>
<table>
<tbody></tbody>
</table>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[PL/SQL Sysdate ile ilgili bir kaç kullanım.]]></title>
<link>http://sametcelikbicak.wordpress.com/2009/11/15/plsql-sysdate-ile-ilgili-bir-kac-kullanim/</link>
<pubDate>Sun, 15 Nov 2009 17:35:22 +0000</pubDate>
<dc:creator>sametcelikbicak</dc:creator>
<guid>http://sametcelikbicak.wordpress.com/2009/11/15/plsql-sysdate-ile-ilgili-bir-kac-kullanim/</guid>
<description><![CDATA[Bulunduğumuz günün adınıa almak için select to_char(sysdate,&#8217;DAY&#8217;) from dual &gt;&gt; ]]></description>
<content:encoded><![CDATA[Bulunduğumuz günün adınıa almak için select to_char(sysdate,&#8217;DAY&#8217;) from dual &gt;&gt; ]]></content:encoded>
</item>
<item>
<title><![CDATA[Logging in PL/SQL]]></title>
<link>http://dioncho.wordpress.com/2009/11/10/logging-in-plsql/</link>
<pubDate>Tue, 10 Nov 2009 08:40:42 +0000</pubDate>
<dc:creator>Dion Cho</dc:creator>
<guid>http://dioncho.wordpress.com/2009/11/10/logging-in-plsql/</guid>
<description><![CDATA[What is the best debugging tool ever invented in the history of the programming langauge? We have a ]]></description>
<content:encoded><![CDATA[What is the best debugging tool ever invented in the history of the programming langauge? We have a ]]></content:encoded>
</item>
<item>
<title><![CDATA[Siebel Consultant- PERM- Easton, PA area.]]></title>
<link>http://manishapatelblog.wordpress.com/2009/11/09/siebel-consultant-perm-easton-pa-area/</link>
<pubDate>Mon, 09 Nov 2009 20:59:56 +0000</pubDate>
<dc:creator>manishapatelblog</dc:creator>
<guid>http://manishapatelblog.wordpress.com/2009/11/09/siebel-consultant-perm-easton-pa-area/</guid>
<description><![CDATA[Client is looking for a Perm Siebel Certified Technician/Configurator. Must be Green Card/ Citizens ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Client is looking for a Perm Siebel Certified Technician/Configurator. Must be Green Card/ Citizens ONLY- Great Salary and Benefits. Easton, PA area.</p>
<p>Experience with Siebel CRM.<br />
Experience with configuring Siebel Tools, eScript, Workflow and Assignment Manager.<br />
Experience with EIM, EAI, Integration Objects, EBC, VBC, Business Services and Web Services.<br />
Experience writing SQL, PL/SQL and SQL Loader.<br />
Experience with installation and administration of Siebel servers.<br />
Experience in estimating level of effort and complexity of requirements.<br />
Experience with hands-on custom software development, code reviews and technical design.<br />
Bachelor&#8217;s degree in an IT related area or equivalent work experience.<br />
Siebel Certified<br />
5+ years&#8217; of Experience delivering quality Siebel CRM solutions.<br />
Experience delivering two + full life cycle implementation.<br />
Experience with Siebel Configuration; Business Components, Views, Applets, Roles &#38; Responsibilities, Workflow, eScript, SmartScript.<br />
Experience with event driven Configuration, such as Workflow Policies and Run-time Events.<br />
Experience configuring VBCs and EBCs.<br />
Experience integrating Siebel with other applications. Exposure to EAI, EIM, integration objects, integration error handling, and integration concepts (real-time, batch, sync/async).<br />
Experience with web service configuration for both subscribing to external web services and exposing Siebel business layer objects as web services.<br />
Experience gathering and documenting business and functional requirements.<br />
Excellent Understanding of Siebel Development process, architecture, and data model.<br />
 Working knowledge of db technologies and relational database concepts.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[PLSQL Concepts]]></title>
<link>http://mangaltripathi.wordpress.com/2009/11/09/plsql-urls/</link>
<pubDate>Mon, 09 Nov 2009 12:14:46 +0000</pubDate>
<dc:creator>mangaltripathi</dc:creator>
<guid>http://mangaltripathi.wordpress.com/2009/11/09/plsql-urls/</guid>
<description><![CDATA[Below are the list of URLs, which I found to be very good. I have also provided a small abstract fro]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Below are the list of URLs, which I found to be very good. I have also provided a small abstract from the reference site. For more detail, please refer the URL.</p>
<p>First, I will thank and acknowledge all the authors and Gurus who have shared their knowledge through websites and blogs.</p>
<ol>
<li>
<h4><a href="http://www.oracle.com/technology/oramag/oracle/06-jan/o16plsql.html" target="_blank">Defining Arrays in Oracle </a></h4>
<ul>
<li>Create a collection using the Associative Arrays i.e. <span style="color:#993300;"><span style="color:#000000;">&#60;code&#62;TYPE &#60;type name&#62; TABLE OF &#60;like NUMBER&#62; INDEX BY PLS_INTEGER </span><span style="color:#000000;">&#60;/code&#62;and then create another TABLE type based on the previous one.</span> <span style="color:#000000;">This creates a 2D</span> <span style="color:#000000;">Array of unlimited size.<br />
</span></span></li>
</ul>
</li>
<li>
<h4><a href="http://www.oracle.com/technology/oramag/oracle/06-mar/o26plsql.html" target="_blank">Remove Characters using Translate Function</a></h4>
<ul>
<li><span style="color:#000000;">TRANSLATE ( &#60;your_string&#62; , &#8216;#&#8217;  &#124;&#124;  &#60;characters_to_be_removed&#62;, &#8216;#&#8217;)</span></li>
<li>Here, # was used by the author as a placeholder and which can be any character-set which should not be present in th<span style="color:#000000;">e &#60;your_string&#62;</span></li>
</ul>
</li>
<li>
<h4><a href="http://www.oracle.com/technology/oramag/oracle/06-mar/o26plsql.html" target="_blank">Ref-Cursor variables</a></h4>
<ul>
<li>The Ref-cursor value can also be passed as an OUT parameter</li>
<li><span style="color:#000000;">PROCEDURE &#60;yr_proc&#62; (&#60;in_var&#62; OUT SYS_REFCURSOR),<strong> </strong>now within the procedure just OPEN the cursor OPEN &#60;in_var&#62; FOR &#60;lv_query&#62;</span></li>
</ul>
</li>
<li>
<h4><a href="http://www.oracle.com/technology/oramag/oracle/08-sep/o58plsql.html" target="_blank">Best practices for changing headers and handling different WHERE clauses</a></h4>
</li>
<li></li>
<li><span style="color:#993300;"><span style="color:#000000;">Will add more&#8230;</span><br />
</span></li>
</ol>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Authid Definer &amp; Current_User in Oracle PL/SQL Procedure]]></title>
<link>http://raghuveerbabu.wordpress.com/2009/11/06/authid-definer-current_user-in-oracle-plsql-procedure/</link>
<pubDate>Fri, 06 Nov 2009 10:06:44 +0000</pubDate>
<dc:creator>raghuveerbabu</dc:creator>
<guid>http://raghuveerbabu.wordpress.com/2009/11/06/authid-definer-current_user-in-oracle-plsql-procedure/</guid>
<description><![CDATA[Consider you’ve same tables (dummy_table) in two different users (assume user A &amp; user B). You’r]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><font size="2">Consider you’ve same tables (dummy_table) in two different users (assume user A &#38; user B). You’re creating a procedure in user A to update the values of dummy_table. By granting the execute privilege on the procedure to insert into the dummy_table to user B, now you can define in a procedure to update it in either user A’s table or user B’s table.</font></p>
<p><font size="2">Confusing..? Lets go into the practicals..</font></p>
<ul>
<li><font size="2">In User A, create the following table. </font></li>
</ul>
<blockquote><p><font size="2">CREATE TABLE dummy_tab(my_date DATE);</font></p>
</blockquote>
<ul>
<li><font size="2">Now, create a procedure in User A, to insert into the dummy_tab </font></li>
</ul>
<blockquote><p><font size="2">CREATE OR REPLACE PROCEDURE update_dummy_tab AUTHID DEFINER AS        <br />BEGIN         <br />INSERT INTO dummy_tab VALUES(SYSDATE);         <br />COMMIT;         <br />END;         <br />/</font></p>
</blockquote>
<ul>
<li><font color="#666666" size="2">Grant the execute privilege to user B to run the procedure.</font> </li>
</ul>
<blockquote><p><font size="2">GRANT EXECUTE ON update_dummy_tab TO userb;</font></p>
</blockquote>
<ul>
<li><font size="2">Now login as user B &#38; create the dummy_tab table.</font> </li>
</ul>
<blockquote><p><font size="2">CREATE TABLE dummy_tab(my_date DATE);</font></p>
</blockquote>
<ul>
<li><font size="2">Run the procedure in user B which is created in user A as follows:</font> </li>
</ul>
<blockquote><p><font size="2">CALL usera.update_dummy_tab();</font></p>
</blockquote>
<ul>
<li><font size="2">If you select the values of dummy_tab in user A, it’s updated with sysdate..</font><br />
<blockquote>
<p><font size="2">&#160;&#160;&#160;&#160; <strong>MY_DATE&#160; <br />&#160;&#160;&#160;&#160; </strong>11/6/2009 3:17:12 PM</font></p>
</blockquote>
</li>
</ul>
<p>Now lets try to update the user A’s procedure to update user B’s dummy table.</p>
<ul>
<li>Modify the procedure with AUTHID CURRENT_USER as follows: </li>
</ul>
<blockquote><p>CREATE OR REPLACE PROCEDURE update_dummy_tab AUTHID CURRENT_USER AS      <br />BEGIN       <br />INSERT INTO dummy_tab VALUES(SYSDATE);       <br />COMMIT;       <br />END;       <br />/</p>
</blockquote>
<ul>
<li>Run the procedure in user B again.. </li>
</ul>
<blockquote><p><font size="2">CALL usera.update_dummy_tab();</font></p>
</blockquote>
<ul>
<li>Then select the user B’s dummy_tab table.. You’ll be surprised that it’s filled with the current sysdate.<br />
<blockquote>
<p><strong>&#160;&#160;&#160;&#160;&#160; MY_DATE            <br /></strong>&#160;&#160;&#160;&#160;&#160; 11/6/2009 3:27:40 PM</p>
</blockquote>
<p>So, by using AUTHID CURRENT_USER in the procedure, it takes the local tables of the user. If the table is not present, it’ll throw out the error.</p>
<p>By default AUTHID DEFINER is implicitly specified in the procedure. Its not necessary to specify explicitly. Only for AUTHID CURRENT_USER it should be specified.</p>
</li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Oracle PL/SQL quick start tutorials]]></title>
<link>http://sqlweblog.wordpress.com/2009/11/05/oracle-plsql-quick-start-tutorials/</link>
<pubDate>Thu, 05 Nov 2009 17:01:08 +0000</pubDate>
<dc:creator>SQLWebLogger</dc:creator>
<guid>http://sqlweblog.wordpress.com/2009/11/05/oracle-plsql-quick-start-tutorials/</guid>
<description><![CDATA[http://sirius.cs.ucdavis.edu/teaching/sqltutorial/tutorial.pdf]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a title="http://sirius.cs.ucdavis.edu/teaching/sqltutorial/tutorial.pdf" href="http://sirius.cs.ucdavis.edu/teaching/sqltutorial/tutorial.pdf">http://sirius.cs.ucdavis.edu/teaching/sqltutorial/tutorial.pdf</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Deshabilitar "SAVE" en un bloque]]></title>
<link>http://amosqueda.wordpress.com/2009/11/04/deshabilitar-save-en-un-bloque/</link>
<pubDate>Thu, 05 Nov 2009 05:07:15 +0000</pubDate>
<dc:creator>devdb</dc:creator>
<guid>http://amosqueda.wordpress.com/2009/11/04/deshabilitar-save-en-un-bloque/</guid>
<description><![CDATA[En oracle forms, cuando se tiene el escenario donde un bloque en particular no se permite guardar, e]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>En oracle forms, cuando se tiene el escenario donde un bloque en particular<!--more--> no se permite guardar, es decir, los datos ingresados no son relevantes; se hace uso de paquete APP_SPECIAL</p>
<p>ejemplo:</p>
<p>en el bloque que se desea deshabilidar<br />
usar el disparador &#8220;PRE-BLOCK&#8221; y introducir el código <strong>app_special.enable(&#8216;SAVE&#8217;, PROPERTY_OFF); </strong><br />
ahora para que este botón se encuentre disponible en los demás bloques a nivel módulo en el mismo disparador (PRE-BLOCK)<br />
introducir el código <strong>app_special.Enable(&#8216;SAVE&#8217;, PROPERTY_ON);</strong></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Logger, A PL/SQL Logging and Debugging Utility]]></title>
<link>http://tylermuth.wordpress.com/2009/11/03/logger-a-plsql-logging-and-debugging-utility/</link>
<pubDate>Tue, 03 Nov 2009 21:55:04 +0000</pubDate>
<dc:creator>Tyler Muth</dc:creator>
<guid>http://tylermuth.wordpress.com/2009/11/03/logger-a-plsql-logging-and-debugging-utility/</guid>
<description><![CDATA[I&#8217;ve been gradually building out a logging utility for PL/SQL over the last year or so. It]]></description>
<content:encoded><![CDATA[I&#8217;ve been gradually building out a logging utility for PL/SQL over the last year or so. It]]></content:encoded>
</item>
<item>
<title><![CDATA[Oracle PL/SQL splitting function]]></title>
<link>http://itangel.wordpress.com/2009/11/02/oracle-plsql-split/</link>
<pubDate>Mon, 02 Nov 2009 08:19:01 +0000</pubDate>
<dc:creator>itangel</dc:creator>
<guid>http://itangel.wordpress.com/2009/11/02/oracle-plsql-split/</guid>
<description><![CDATA[I needed to spilt (tokenize) a string in Oracle SQL and I wanted do it simply and I found a really u]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I needed to spilt (tokenize) a string in Oracle SQL and I wanted do it simply and I found a really useful function:</p>
<p><code><br />
function get_split(the_list  varchar2,<br />
                        the_index number,<br />
                        delim     varchar2 := '&#124;' ) return varchar2<br />
  is<br />
     start_pos number;<br />
     end_pos   number;<br />
  begin<br />
      if the_index = 1 then<br />
        start_pos := 1;<br />
      else<br />
        start_pos := instr(the_list, delim, 1, the_index - 1);<br />
        if start_pos = 0 then<br />
          return null;<br />
        else<br />
          start_pos := start_pos + length(delim);<br />
        end if;<br />
      end if;<br />
      end_pos := instr(the_list, delim, start_pos, 1);<br />
      if end_pos = 0 then<br />
        return substr(the_list, start_pos);<br />
       else<br />
       return substr(the_list, start_pos, end_pos - start_pos);<br />
      end if;<br />
    end get_split;</code></p>
<p>So now I could do a select :<br />
   <code>select <strong>get_split</strong>('0&#124;1&#124;0',2) from dual;</code> &#8211;&#62; &#8216;1&#8242; </p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[pl/sqlのドキュメント生成]]></title>
<link>http://tonecolor.wordpress.com/2009/11/01/plsql%e3%81%ae%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88%e7%94%9f%e6%88%90/</link>
<pubDate>Sun, 01 Nov 2009 05:05:42 +0000</pubDate>
<dc:creator>tara123</dc:creator>
<guid>http://tonecolor.wordpress.com/2009/11/01/plsql%e3%81%ae%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88%e7%94%9f%e6%88%90/</guid>
<description><![CDATA[最近、pl/sqlのコードを書いてみたりしているが、ドキュメントの生成も欲しいところ、探すとPLDocというものがあったのでちょっと試した。 javadocと同じ感じで使用すると、ドキュメントをちゃん]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>最近、pl/sqlのコードを書いてみたりしているが、ドキュメントの生成も欲しいところ、探すとPLDocというものがあったのでちょっと試した。</p>
<p>javadocと同じ感じで使用すると、ドキュメントをちゃんと生成してくれた。</p>
<p><a href="http://tonecolor.wordpress.com/files/2009/11/snap10.png"><img class="alignnone size-medium wp-image-368" title="snap10" src="http://tonecolor.wordpress.com/files/2009/11/snap10.png?w=300" alt="snap10" width="300" height="209" /></a>この手のツールはあると非常に助かるが、pl/sqlのようなOracle社しかエンジン開発しないような言語は初めからOracle社として用意すべきではないだろうか？</p>
<p>いつかこの手のツールがOracleに標準装備されることを期待する。</p>
<p>&#160;</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Automatically Backuping Apex Applications]]></title>
<link>http://sungur.wordpress.com/2009/10/31/automatically-backuping-apex-applications/</link>
<pubDate>Sat, 31 Oct 2009 10:45:38 +0000</pubDate>
<dc:creator>Ahmet Fuat Sungur</dc:creator>
<guid>http://sungur.wordpress.com/2009/10/31/automatically-backuping-apex-applications/</guid>
<description><![CDATA[Automatically Backuping Apex Applications We can export our apex applications as an sql file in ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Automatically Backuping Apex Applications </p>
<p>We can export our apex applications as an sql file in &#8220;Home&#62;Application Builder&#62;Application $ID&#62;Export / Import&#62;Export&#8221; menu. You can do this as manually, so if you want to backup your apex application(s) you should do this for each time for each application.</p>
<p>As you guess this operation runs a plsql command in background to export application. </p>
<p>&#8220;wwv_flow_utilities&#8221; public package of apex, includes &#8220;export_application_to_clob&#8221; function that returns clob variable that containts sql statements. These sql statements those are application metadata that will be imported your workspace. Spec part of function is below :</p>
<div class="plsql" style="font-family:Courier New;color:#006;background-color:#f0f0f0;border:1px dotted;font-size:12px;white-space:normal;">
<p>function export_application_to_clob (<br />
   p_application_id   in number,<br />
   p_export_saved_reports in varchar2 default &#8216;N&#8217;)<br />
   return clob<br />
   ;</p>
</div>
<p>Application ID is a number that user specified or automatically got from apex. That is on right of f?p= parameter of url string. You should specify application id to export application. Another parameter is p_export_saved_reports is optional, if you want to export saved report you can set this as &#8216;Y&#8217;.</p>
<p>You can write a dbms_scheduler job that runs this plsql for every specified interval time. Or you can write a unix shell script that produces an sql file, put this shell script to crontab to run this backup operations for every specified interval time. Or anything else&#8230;</p>
<p>Also you can export only a page of an application, this function is under wwv_flow_utilities package too, spec part of this :</p>
<div class="plsql" style="font-family:Courier New;color:#006;background-color:#f0f0f0;border:1px dotted;font-size:12px;white-space:normal;">
<p>function export_page_to_clob (<br />
   p_application_id   in number,<br />
   p_page_id          in number)<br />
   return CLOB<br />
   ;</p>
</div>
<p>Example :</p>
<div class="plsql" style="font-family:Courier New;color:#006;background-color:#f0f0f0;border:1px dotted;font-size:12px;white-space:normal;">
<p>CREATE TABLE EXPORT_CLOB<br />
(<br />
    APP_EXPORT CLOB<br />
);</p>
<p>BEGIN</p>
<p>INSERT INTO EXPORT_CLOB<br />
VALUES (WWV_FLOW_UTILITIES.EXPORT_APPLICATION_TO_CLOB(&#8216;107&#8242;));</p>
<p>END;</p>
<p>SELECT length(app_export) FROM EXPORT_CLOB;</p>
<p>954956</p>
</div>
<p>To backup your all of applications you can get application id from &#8220;select * from apex_applications&#8221;.</p>
<p>This example was tested on Oracle 11.1.0.6 and Apex 3.2.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[No sum for interval day to second?]]></title>
<link>http://stefanoravec.wordpress.com/2009/10/30/no-sum-for-interval-day-to-second/</link>
<pubDate>Fri, 30 Oct 2009 13:52:41 +0000</pubDate>
<dc:creator>stefanoravec</dc:creator>
<guid>http://stefanoravec.wordpress.com/2009/10/30/no-sum-for-interval-day-to-second/</guid>
<description><![CDATA[I just wonder why ORACLE didn&#8217;t implement sum of interval day to second datatype. CREATE OR RE]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I just wonder why ORACLE didn&#8217;t implement sum of interval day to second datatype.</p>
<p><code></p>
<pre>
CREATE OR REPLACE TYPE sum_interval AS OBJECT
(

/* type implements oracles data cartridge interface to compute sum of day to second interval values */

   duration INTERVAL DAY TO SECOND, --duration accumulator

   CONSTRUCTOR FUNCTION sum_interval RETURN SELF AS RESULT
      PARALLEL_ENABLE,

   STATIC FUNCTION odciaggregateinitialize(ctx IN OUT sum_interval) RETURN NUMBER,

   MEMBER FUNCTION odciaggregateiterate
   (
      SELF  IN OUT sum_interval,
      VALUE IN INTERVAL DAY TO SECOND
   ) RETURN NUMBER,

   MEMBER FUNCTION odciaggregatedelete
   (
      SELF  IN OUT sum_interval,
      VALUE IN INTERVAL DAY TO SECOND
   ) RETURN NUMBER,

   MEMBER FUNCTION odciaggregateterminate
   (
      SELF        IN sum_interval,
      returnvalue OUT INTERVAL DAY TO SECOND,
      flags       IN NUMBER
   ) RETURN NUMBER,

   MEMBER FUNCTION odciaggregatemerge
   (
      SELF IN OUT sum_interval,
      ctx  IN sum_interval
   ) RETURN NUMBER
)
;
/

CREATE OR REPLACE TYPE BODY sum_interval IS

   -------------------------------------------------------------------------------------------------
   CONSTRUCTOR FUNCTION sum_interval RETURN SELF AS RESULT
      PARALLEL_ENABLE IS
   BEGIN
      RETURN;
   END sum_interval;

   -------------------------------------------------------------------------------------------------
   STATIC FUNCTION odciaggregateinitialize(ctx IN OUT sum_interval) RETURN NUMBER IS
   BEGIN
      ctx := sum_interval();
      RETURN odciconst.success;
   END odciaggregateinitialize;

   -------------------------------------------------------------------------------------------------
   MEMBER FUNCTION odciaggregateiterate
   (
      SELF  IN OUT sum_interval,
      VALUE IN INTERVAL DAY TO SECOND
   ) RETURN NUMBER IS
   BEGIN
      IF SELF.duration IS NULL THEN
         SELF.duration := VALUE;
      ELSE
         SELF.duration := SELF.duration + VALUE;
      END IF;
      RETURN odciconst.success;
   END odciaggregateiterate;

   -------------------------------------------------------------------------------------------------
   MEMBER FUNCTION odciaggregateterminate
   (
      SELF        IN sum_interval,
      returnvalue OUT INTERVAL DAY TO SECOND,
      flags       IN NUMBER
   ) RETURN NUMBER IS
   BEGIN
      returnvalue := SELF.duration;
      RETURN odciconst.success;
   END odciaggregateterminate;

   -------------------------------------------------------------------------------------------------
   MEMBER FUNCTION odciaggregatedelete
   (
      SELF  IN OUT sum_interval,
      VALUE IN INTERVAL DAY TO SECOND
   ) RETURN NUMBER IS
   BEGIN
      SELF.duration := SELF.duration - VALUE;
      RETURN odciconst.success;
   END odciaggregatedelete;

   -------------------------------------------------------------------------------------------------
   MEMBER FUNCTION odciaggregatemerge
   (
      SELF IN OUT sum_interval,
      ctx  IN sum_interval
   ) RETURN NUMBER IS
   BEGIN
      IF ctx.duration IS NULL THEN
         NULL;
      ELSE
         SELF.duration := SELF.duration + ctx.duration;
      END IF;
      RETURN odciconst.success;
   END odciaggregatemerge;

END;
/

create or replace function fce_sum_interval(duration interval day to second) return interval day to second
  parallel_enable
  aggregate using sum_interval;
/

select fce_sum_interval(numtodsinterval(level, 'minute')) from dual connect by level &#60;= 10;
</pre>
<p></code></p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
