BC remote Oracle DBA - Call (800) 766-1884  
Oracle Consulting Oracle Training Development

Remote DBA

Remote DBA Plans  

Remote DBA Service

Remote DBA RAC

   
Remote DBA Oracle Home
Remote DBA Oracle Training
Remote DBA SQL Tuning Consulting
Remote DBA Oracle Tuning Consulting
Remote DBA Data Warehouse Consulting
Remote DBA Oracle Project Management
Remote DBA Oracle Security Assessment
Remote DBA Unix Consulting
Burleson Books
Burleson Articles
Burleson Web Courses
Burleson Qualifications
Oracle Links
Remote DBA Oracle Monitoring
Remote DBA Support Benefits
Remote DBA Plans & Prices
Our Automation Strategy
What We Monitor
Oracle Apps Support
Print Our Brochure
Contact Us (e-mail)
Oracle Job Opportunities
Oracle Consulting Prices





   

 

 

 

Remote DBA services

Remote DBA Support

Remote DBA RAC

Remote DBA Reasons

Remote Oracle Tuning

Remote DBA Links

Oracle DBA Support

Oracle DBA Forum

Oracle Disaster

Oracle Training

Oracle Tuning

Oracle Training

 Remote DBA SQL Server

Remote MSSQL Consulting

Oracle DBA Hosting

Oracle License Negotiation

 

 


 

 

 

 

 
 

EnterpriseDB: SQL Data Types

Oracle Tips by Burleson Consulting
 

Data type support in EnterpriseDB Advanced Server is very robust (see Chapter 3 for details).  In addition to supporting almost all of the Oracle data types, EnterpriseDB also supports all of the PostgreSQL data types.  Not all PostgreSQL data types are compatible with SPL.

Simple data types such as VARCHAR2 or NUMBER are transparently translated to PostgreSQL style data types by the EnterpriseDB server.  The DATE data type, when used in Redwood mode, is automatically translated to a Timestamp data type.

EnterpriseDB does not currently support Oracle style Object types.  EnterpriseDB does support PostgreSQL style object types but those types do not allow OOP style methods and are not compatible with Oracle object types. 

EnterpriseDB, the company, has publicly stated that they intend to support Oracle style objects with methods.  Once they do provide support for those object types an entirely new class of enterprise application will be open to easy migration to EnterpriseDB.  In the meantime, object based applications cannot be automatically migrated. 

While it is not possible to automate the migration, it is possible to use built-in support in EnterpriseDB to make it possible to manually migrate an application.  For example, because EnterpriseDB does not support Object types, it also does not support the XMLType (which is an implementation of an Oracle style object).

It is not that difficult to create a code-based solution, though.  In this example, I will emulate a solution to using SQLX in your application. SQLX is an ANSI standard method for generating XML documents from databases.  Oracle provides a very robust implementation of SQLX.

An example SQLX query might be:

SELECT XMLElement("Employee",
  XMLAttributes(deptno as "deptno", (select dname
                           from dept
                           where dept.deptno = emp.deptno) as "dname"),
  XMLForest( emp.ename,
             emp.empno,
             emp.job ))
FROM emp
HERE ename = 'FORD'

The output from this select would be:

<Employee deptno="20" dname="RESEARCH">
  <ENAME>FORD</ENAME>
  <EMPNO>7902</EMPNO>
  <JOB>ANALYST</JOB>
</Employee>

EnterpriseDB cannot generate this data in this way out of the box.  We can however emulate this functionality by writing some of our own code.

The first thing to do is to create an XMLElement function that does what we want it to do.  Remember when porting an application, you don't have to meet the ANSI standards for that functionality, you just need to support those features that are required to port the application.

In this case, we need a function that has a signature as close as possible to the ANSI function and that will return the data we need.

The XMLElement function takes two parameters.  The first parameter is an alias or name that will be used within an element tag.  Because it is an alias, it is passed in with double quote (") instead of a single quote (').  This will impact the implementation below.

The second parameter is the tag value.  So if we call XMLElement( "name", 'Lewis') we should see XML that looks like <name>Lewis</name>.  Alternatively, if we call it within a SQL statement, we would expect to see data values.

I will create the XML function by using simple SPL:

CREATE OR REPLACE FUNCTION public.xmlelement (
    p_name VARCHAR,
    p_value VARCHAR
    )
RETURN varchar AS
    v_ret_string VARCHAR2(32000);
  BEGIN 

    v_ret_string := '<' || p_name; 

    IF p_value IS NULL
    THEN
      v_ret_string := v_ret_string || ' />';
    ELSE
      v_ret_string := v_ret_string || '>' ||
           p_value ||
           '</' || p_name || '>';
    END IF; 

    RETURN v_ret_string;
  END;


I will call the XMLElement function in Oracle:

SELECT XMLElement ("Employee", ename)
FROM emp
WHERE ename = 'FORD'

I get this result back:

<Employee>FORD</Employee>

I compile the above function in EnterpriseDB and call the new XMLElement function (notice that the double quote is now a single quote):

SELECT XMLElement ('Employee', ename)
FROM emp
WHERE ename = 'FORD'

I get this result back from EnterpriseDB:

<Employee>FORD</Employee>

The original query also contains the XMLForest function.  XMLForest is another SQLX function.  This function accepts a varying list of parameters and creates an XML Document from those parameters.  It uses the parameter name to alias (which names the XML tag) the values.

So in Oracle, when I run this query:

SELECT XMLForest ( emp.ename,
             emp.empno,
             emp.job )
FROM emp
WHERE ename = 'FORD'

I get this output:

<ENAME>FORD</ENAME>
<EMPNO>7902</EMPNO> 

<JOB>ANALYST</JOB>

In EnterpriseDB, I will write another very basic SPL procedure: 

CREATE OR REPLACE FUNCTION XMLFOREST(
    p_attr1 IN VARCHAR2,
    p_label1 IN VARCHAR2,
    p_attr2 IN VARCHAR2 DEFAULT NULL,
    p_label2 IN VARCHAR2 DEFAULT NULL,
    p_attr3 IN VARCHAR2 DEFAULT NULL,
    p_label3 IN VARCHAR2 DEFAULT NULL,
    p_attr4 IN VARCHAR2 DEFAULT NULL,
    p_label4 IN VARCHAR2 DEFAULT NULL,
    p_attr5 IN VARCHAR2 DEFAULT NULL,
    p_label5 IN VARCHAR2 DEFAULT NULL)
  RETURN VARCHAR2
  AS

   
v_return_string VARCHAR2(32000);
  BEGIN
    v_return_string := XMLELEMENT( p_label1, p_attr1 ); 

    IF p_attr2 IS NOT NULL
      AND
       p_label2 IS NOT NULL
    THEN
      v_return_string := v_return_string || XMLELEMENT( p_label2, p_attr2 );
    END IF;
 
    IF p_attr3 IS NOT NULL
      AND
       p_label3 IS NOT NULL

  
  THEN
      v_return_string := v_return_string || XMLELEMENT( p_label3, p_attr3 );
    END IF; 

    IF p_attr4 IS NOT NULL
      AND
       p_label4 IS NOT NULL
    THEN
      v_return_string := v_return_string || XMLELEMENT( p_label4, p_attr4 );
    END IF; 

    IF p_attr5 IS NOT NULL
      AND
       p_label5 IS NOT NULL

   
THEN
      v_return_string := v_return_string || XMLELEMENT( p_label5, p_attr5 );
    END IF; 

    RETURN v_return_string;
  END;


This function is slightly more complicated than the XMLElement function but not by much.  Because the XMLForest function accepts a varying number of parameters, I chose to create up to five columns.  You can extend that by adding additional parameters.

In addition, SPL is not able to deduce the column names from within the function.  That data is not available.  Instead of feeling stuck, I chose to slightly alter my query by passing in alias names:

SELECT XMLForest (ename, 'ENAME',
                 to_char(empno), 'EMPNO',
                 job, 'JOB')
  FROM emp
  WHERE ename = 'FORD'

I get this output from EnterpriseDB:

<ENAME>FORD</ENAME>
<EMPNO>7902</EMPNO>
 

<JOB>ANALYST</JOB>

Finally, the original query included an XMLAttribute.  XMLAttribute modifies an XMLElement call by adding attributes to an element.  In the case of the original query, it added deptno and dname. 

I found that I could not easily emulate the behavior of XMLAttribute with pure SPL.  Instead, I chose to use PL/TCLU and create a function using that language.  It is a very simple function:

CREATE OR REPLACE FUNCTION XMLAttributes(text) RETURNS text AS $$
  set val " " 

  spi_exec -array C $1 

  foreach key [array names C] {
    if {$key == ".tupno"} {
    } else {
    set val "$val$key=\"$C($key)\" " }
  } 

  return $val
$$ LANGUAGE pltclu;
 

This function accepts a SQL statement (as a string) as input and outputs an attribute list.  For example, if I run this query (Note XMLAttribute by definition in SQLX is meant to be embedded within an XMLElement call):

SELECT  XMLAttributes('select deptno, dname
                         from dept
                         where dept.deptno = ' || emp.deptno)
FROM emp
WHERE ename = 'FORD'


In EnterpriseDB, I get
this output:

  dname="RESEARCH" deptno="20" 

The original query and output:

SELECT XMLElement ("Employee",
  XMLAttributes(deptno as "deptno", (select dname
                           from dept
                           where dept.deptno = emp.deptno) as "dname"),
  XMLForest ( emp.ename,
             emp.empno,
             emp.job ))
FROM emp
WHERE ename = 'FORD'

The output from this select would be:

<Employee deptno="20" dname="RESEARCH">
  <ENAME>FORD</ENAME>
  <EMPNO>7902</EMPNO>
  <JOB>ANALYST</JOB>
</Employee>

Can now be changed and run in EnterpriseDB as:

SELECT XMLElement ('Employee',
       XMLAttributes('select dname, deptno
                        from dept
                        where deptno = ' || deptno),
       XMLForest ( ename, 'ENAME',
                  to_char(empno), 'EMPNO',
                  job, 'JOB'))
FROM emp
WHERE ename = 'FORD'

The output is:

<Employee dname="RESEARCH" deptno="20" >
  <ENAME>FORD</ENAME>
  <EMPNO>7902</EMPNO>
  <JOB>ANALYST</JOB>
</Employee>

This is exactly what I wanted and expected.  If you look at the two queries closely, you can see the obvious differences.  Those differences are fairly minor and once the rules are known, could be automated.

The short story here is that while EnterpriseDB may not support every feature you might need, it provides many tools to work around those deficiencies.  Over time, EnterpriseDB will support more and more of these features.  At that time, you can choose to migrate your custom code to the newly enhanced functionality or stay with your custom code.

You may download the entire set of functions (XMLElement, XMLForest and XMLAttribute) from the code depot.  These functions are in the file chap8_sqlx.sql.

* chap8_sql.sql

-- Create an SPL function that emulates SQL/X xmlElement

CREATE OR REPLACE FUNCTION public.xmlelement (
    p_name VARCHAR,
    p_value VARCHAR
    )
RETURN varchar AS
    v_ret_string VARCHAR2(32000);

  BEGIN

    v_ret_string := '<' || p_name; 

    IF p_value IS NULL
    THEN
      v_ret_string := v_ret_string || ' />';
    ELSE
      v_ret_string := v_ret_string || '>' ||
           p_value ||
           '</' || p_name || '>';
    END IF;


   
RETURN v_ret_string;
  END;

-- Test a function that emulates SQL/X xmlElement

SELECT XMLElement ('Employee', ename)
FROM emp
WHERE ename = 'FORD'


-- Create an SPL functio
n that emulates SQL/X xmlForest

CREATE OR REPLACE FUNCTION XMLFOREST(
    p_attr1 IN VARCHAR2,
    p_label1 IN VARCHAR2,
    p_attr2 IN VARCHAR2 DEFAULT NULL,
    p_label2 IN VARCHAR2 DEFAULT NULL,
    p_attr3 IN VARCHAR2 DEFAULT NULL,
    p_label3 IN VARCHAR2 DEFAULT NULL,
    p_attr4 IN VARCHAR2 DEFAULT NULL,
    p_label4 IN VARCHAR2 DEFAULT NULL,
    p_attr5 IN VARCHAR2 DEFAULT NULL,
    p_label5 IN VARCHAR2 DEFAULT NULL)

 
RETURN VARCHAR2
  AS
    v_return_string VARCHAR2(32000);
  BEGIN
    v_return_string := XMLELEMENT( p_label1, p_attr1 );
 
    IF p_attr2 IS NOT NULL
      AND
       p_label2 IS NOT NULL
    THEN

   
   v_return_string := v_return_string || XMLELEMENT( p_label2, p_attr2 );
    END IF;
 
    IF p_attr3 IS NOT NULL
      AND
       p_label3 IS NOT NULL
    THEN
      v_return_string := v_return_string || XMLELEMENT( p_label3, p_attr3 );
    END IF;
 

    IF p_attr4 IS NOT NULL
      AND
       p_label4 IS NOT NULL
    THEN
      v_return_string := v_return_string || XMLELEMENT( p_label4, p_attr4 );
    END IF; 

    IF p_attr5 IS NOT NULL
      AND
       p_label5 IS NOT NULL
    THEN
      v_return_string := v_return_string || XMLELEMENT( p_label5, p_attr5 );
    END IF;

    RETURN v_return_string;  

  END;

-- Test a function that emulates SQL/X xmlForest

SELECT XMLForest (ename, 'ENAME',
                 to_char(empno), 'EMPNO',
                 job, 'Job')
  FROM emp
  WHERE ename = 'FORD'

-- Create a TCL function that emulates SQL/X xmlAttribute

CREATE OR REPLACE FUNCTION XMLAttributes(text) RETURNS text AS $$
  set val " " 

  spi_exec -array C $1 

  foreach key [array names C] {
    if {$key == ".tupno"} {
    } else {
    set val "$val$key=\"$C($key)\" " }

 

  return $val
$$ LANGUAGE pltclu;


-- Test a function that emulates SQL/X xmlAttribute

SELECT  XMLAttributes('select deptno, dname
                         from dept
                         where dept.deptno = ' || emp.deptno)
FROM emp
WHERE ename = 'FORD';

-- Test all of the SQL/X functions

SELECT XMLElement ('Employee',
       XMLAttributes('select dname, deptno
                        from dept
                        where deptno = ' || deptno),
       XMLForest ( ename, 'ENAME',
                  to_char(empno), 'EMPNO',
                  job, 'JOB'))
FROM emp

WHERE ename = 'FORD';




This is an excerpt from the book "EnterpriseDB: The Definitive Reference" by Rampant TechPress.


Expert Remote DBA

BC is America's oldest and largest Remote DBA Oracle support provider.  Get real Remote DBA experts, call
BC Remote DBA today.

 

 

Remote DBA Service
 

Oracle Tuning Book

 

Advance SQL Tuning Book 

BC Oracle support

Oracle books by Rampant

Oracle monitoring software

 

 

 

 

 

 

BC Remote Oracle Support

Remote DBA

Remote DBA Services

Copyright © 1996 -  2013 by Burleson. All rights reserved.

Oracle® is the registered trademark of Oracle Corporation.



Hit Counter