Sophie

Sophie

distrib > Mandriva > 2008.1 > x86_64 > by-pkgid > 05cd670d8a02b2b4a0ffb1756f2e8308 > files > 10968

php-manual-zh-5.2.4-1mdv2008.1.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML
><HEAD
><TITLE
>SDO Relational Data Access Service Functions</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
REL="HOME"
TITLE="PHP 手册"
HREF="index.html"><LINK
REL="UP"
TITLE="函数参考"
HREF="funcref.html"><LINK
REL="PREVIOUS"
TITLE="SDO_DAS_XML::saveString"
HREF="function.sdo-das-xml-savestring.html"><LINK
REL="NEXT"
TITLE="SDO_DAS_Relational::applyChanges"
HREF="function.sdo-das-relational-applychanges.html"><META
HTTP-EQUIV="Content-type"
CONTENT="text/html; charset=UTF-8"></HEAD
><BODY
CLASS="reference"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>PHP 手册</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="function.sdo-das-xml-savestring.html"
ACCESSKEY="P"
>上一页</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="function.sdo-das-relational-applychanges.html"
ACCESSKEY="N"
>下一页</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="reference"
><A
NAME="ref.sdo.das.rel"
></A
><DIV
CLASS="TITLEPAGE"
><H1
CLASS="title"
>CXLV. SDO Relational Data Access Service Functions</H1
><DIV
CLASS="PARTINTRO"
><A
NAME="AEN204794"
></A
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="sdo.das.rel.intro"
>简介</A
></H1
><P
>&#13;    
     <DIV
CLASS="warning"
><P
></P
><TABLE
CLASS="warning"
BORDER="1"
WIDTH="100%"
><TR
><TD
ALIGN="CENTER"
><B
>警告</B
></TD
></TR
><TR
><TD
ALIGN="LEFT"
><P
>本扩展模块是<SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>实验性</I
></SPAN
>的。本模块的行为,包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随
PHP 以后的发布而改变。使用本扩展模块风险自担。</P
></TD
></TR
></TABLE
></DIV
>
   </P
><P
>&#13;    In order to use the Relational Data Access Service for 
    Service Data Objects,
    you will need to understand some of the concepts behind SDO: 
    the data graph, the data object, the disconnected way of working, 
    the change summary, XPath and property expressions, and so on.
    If you are not familiar with these ideas, you might want to look first at
    <A
HREF="ref.sdo.html"
>the section on SDO</A
>.
    In addition, the Relational DAS makes use of the PDO extension to 
    isolate itself from specifics of different back-end relational databases.
    In order to use the Relational DAS you will need to be able to 
    create and pass a PDO database connection;
    for this reason you might also want to take a look at
    <A
HREF="ref.pdo.html"
>the section on PDO</A
>.
   </P
><P
>&#13;    The job of the Relational DAS is to move data between the application
    and a relational database. In order to do this it needs to be told 
    the mapping between the database entities 
    - tables, columns, primary keys and foreign keys - 
    and the elements of the SDO model 
    - types, properties, containment relationships and so on.
    You specify this information as metadata when you 
    construct the Relational DAS.
   </P
><DIV
CLASS="procedure"
><P
><B
><A
NAME="overview"
></A
>Overview of Operation</B
></P
><OL
TYPE="1"
><LI
CLASS="step"
><P
>&#13;      The first step is to call the Relational DAS's constructor,
      passing the metadata that defines the mapping between 
      database and SDO model.
      There are examples of this below.
     </P
></LI
><LI
CLASS="step"
><P
>&#13;      The next step might be to call the
      <B
CLASS="function"
>executeQuery()</B
>
      or
      <B
CLASS="function"
>executePreparedQuery()</B
>
      methods on the Relational DAS, passing either a literal SQL statement
      for the DAS to prepare and execute, or a prepared statement with 
      placeholders and a list of values to be inserted.
      You may also need to specify a small amount of metadata 
      about the query itself, so that the Relational DAS knows 
      exactly what columns will be returned from the database and 
      in what order. You will also need to pass a PDO database connection.
     </P
><P
>&#13;      The return value from
      <B
CLASS="function"
>executeQuery()</B
>
      or 
      <B
CLASS="function"
>executePreparedQuery()</B
>
      is a normalised data graph containing all the data from the result set.
      For a query that returns data obtained from a number of tables, 
      this graph will contain a number of data objects, 
      linked by SDO containment relationships. 
      There may also be SDO non-containment references within the data.
     </P
><P
>&#13;      Once the query has been executed and the data graph constructed, 
      there is no need for either that instance of the the Relational DAS or 
      the database connection. There are no locks held on the database.
      Both the Relational DAS and the PDO database connection can be 
      garbage collected.
     </P
></LI
><LI
CLASS="step"
><P
>&#13;      Quite possibly the data in the data graph will go through 
      a number of modifications. The data graph can be serialised 
      into the PHP session and so may have a lifetime beyond just 
      one client-server interaction. Data objects can be created 
      and added to the graph, the data objects already in the graph 
      can be deleted, and data objects in the graph can be modified.
     </P
></LI
><LI
CLASS="step"
><P
>&#13;      Finally, the changes made to the data graph can be applied 
      back to the database using the
      <B
CLASS="function"
>applyChanges()</B
>
       method of the Relational DAS. For this, another instance 
       of the Relational DAS  must be constructed, using the 
       same metadata, and another connection to the database obtained.
       The connection and the data graph are passed to
      <B
CLASS="function"
>applyChanges()</B
>.
      At this point the Relational DAS examines the change summary 
      and generates the necessary INSERT, UPDATE and DELETE SQL statements 
      to apply the changes. Any UPDATE and DELETE statements are qualified 
      with the original values of the data so that should the data have 
      changed in the database in the meantime this will be detected.
      Assuming no such collisions have occurred the changes will be 
      committed to the database. The application can then continue to work 
      with the data graph, make more changes and apply them, or can discard 
      it.
     </P
></LI
></OL
></DIV
><P
>&#13;    There are other ways of working with the data in the database: 
    it is possible to just create data objects and write them to the 
    database without a preliminary call to
    <B
CLASS="function"
>executeQuery()</B
>,
    for example. This scenario and others are explored in the
    <A
HREF="ref.sdo.das.rel.html#sdo.das.rel.examples"
>Examples</A
>
    section below.
   </P
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="sdo.das.rel.installation"
>安装</A
></H1
><P
>&#13;    The installation instructions for all the SDO components
    are in the SDO 
    <A
HREF="ref.sdo.html#sdo.installation"
>install</A
>
    section of the SDO documentation.
   </P
><P
>&#13;    In any case, the essential facts are that 
    the Relational DAS is written in PHP and it 
    should be placed somewhere on the PHP
    <A
HREF="ini.core.html#ini.include-path"
>include_path</A
>
    .
   </P
><P
>&#13;    Your application will of course need to include the Relational DAS 
    with a statement like this:
    <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
>
   </P
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="sdo.das.rel.requirements"
>需求</A
></H1
><P
>&#13;    The Relational DAS requires that the SDO extension be installed.
    The SDO extension requires a version of PHP 5.1, and the 
    Relational DAS requires a recent version that contains 
    an important fix for PDO. The most up-to-date information about
    required levels of PHP should be found in the changelog for the 
    package on PECL. At the time of writing, though, the Relational 
    DAS requires the most recent beta level of PHP 5.1, that is 
    PHP 5.1.0.
   </P
><P
>&#13;    The Relational DAS uses PDO to access the relational database,
    and so should run with a variety of different relational databases.
    At the time of writing it has been tested in the following configurations
    <P
></P
><UL
><LI
><P
>&#13;       MySQL 4.1.14, on Windows. 
       The Relational DAS operates correctly with the php_pdo_mysql
       driver that comes with the pre-built binaries for PHP 5.1.0.
      </P
></LI
><LI
><P
>&#13;       MySQL 4.1.13, on Linux. It is necessary to have the most up-to-date
       PDO driver for MySQL, which comes built in to PHP 5.1.0. 
       It may be necessary to uninstall the usual driver that would have 
       come from PECL using 
       <B
CLASS="command"
>pear uninstall pdo_mysql</B
>
       . You will need to configure PHP with the 
       <B
CLASS="command"
>--with-pdo-mysql</B
> option.
      </P
></LI
><LI
><P
>&#13;       DB2 8.2 Personal Edition, on Windows.
       The Relational DAS operates correctly with the
       php_pdo_odbc driver that comes with the pre-built binaries for
       PHP 5.1.0.
      </P
></LI
><LI
><P
>&#13;       DB2 8.2 Personal Developer's Edition, on Linux. 
       The Developer's Edition is needed because it
       contains the include files needed when PHP is configured
       and built. You will need to configure PHP with the 
       <B
CLASS="command"
>--with-pdo-odbc=ibm-db2</B
> option.
      </P
></LI
></UL
>
   </P
><P
>&#13;    The Relational DAS applies changes to the database within
    a user-delimited transaction: that is, it issues a call to 
    <B
CLASS="function"
>PDO::beginTransaction()</B
>
    before beginning to apply changes, and 
    <B
CLASS="function"
>PDO::commit()</B
>
    or 
    <B
CLASS="function"
>PDO::rollback()</B
>
    on completion.
    Whichever database is chosen, the database and the PDO driver
    for the database must support these calls. 
   </P
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="sdo.das.rel.limitations"
>Limitations</A
></H1
><P
>&#13;    There are the following limitations in the current release of the 
    Relational DAS:
    <P
></P
><UL
><LI
><P
>&#13;       No support for nulls. There is no support for SQL NULL type. 
       It is not legal to assign PHP NULL to a data object property
       and the Relational DAS will not write that back as a NULL to the 
       database. If nulls are found in the database on a query, 
       the property will remain unset.
      </P
></LI
><LI
><P
>&#13;       Only two types of SDO relationship. The metadata described below 
       allows the Relational DAS to model just two types of SDO relationship:
        multi-valued containment relationships and single-valued 
        non-containment references. In SDO, whether a property describes a 
        single- or multi-valued relationship, and whether it is containment 
        or non-containment, are independent. The full range of possibilities 
        that SDO allows cannot all be defined. There may be relationships 
        that it would be useful to model but which the current implementation
        cannot manage. 
        One example is a single-valued containment relationship.
      </P
></LI
><LI
><P
>&#13;       No support for the full range of SDO data types. The Relational 
       DAS defines all primitive properties in the SDO model as being 
       of type string. SDO defines a richer set of types containing various
       integer, float, boolean and data and time types. String is adequate 
       for the purposes of the Relational DAS since the combination of PHP,
       PDO and the database will ensure that values passed as strings 
       will be converted to the proper type before being put in the database.
       This does affect some scenarios in which the Relational DAS has 
       to work with a data graph that has come from or will go to a 
       different DAS.
      </P
></LI
><LI
><P
>&#13;       Only one foreign key per table. 
       The metadata only provides the means to specify one foreign key 
       per table. This foreign key may be mapped to one of the two types of 
       SDO relationship supported. Obviously there are some scenarios 
       that cannot be described under this limitation - it is not possible 
       to have two non-containment references from one table to another 
       for example.
      </P
></LI
></UL
>
   </P
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="sdo.das.rel.examples"
>范例</A
></H1
><P
>&#13;    This section illustrates how the Relational DAS can be used to create, 
    retrieve, update and delete data in a relational database.
    Many of the examples are illustrated with a three-table database that 
    contains companies, departments within those companies, and employees 
    that work in those departments. This example is used in a number of 
    places within the SDO literature. See the examples section of the
    <A
HREF="ftp://www6.software.ibm.com/software/developer/library/j-commonj-sdowmt/Commonj-SDO-Specification-v2.0.pdf"
TARGET="_top"
>Service Data Objects specification</A
>
    or the
    <A
HREF="ref.sdo.html#sdo.examples"
>Examples</A
>
    section of the documentation for the SDO extension.
   </P
><P
>&#13;    The Relational DAS is constructed with metadata that defines the 
    relational database and how it should be mapped to SDO.
    The long section that follows describes this metadata and how to 
    construct the Relational DAS. The examples that follow it all assume that
    this metadata is in an included php file.
   </P
><P
>&#13;    The examples below and others can all be found in the
    <TT
CLASS="filename"
>Scenarios</TT
>
    directory in the Relational DAS package.
   </P
><P
>&#13;    The Relational DAS throws exceptions in the event that it finds errors 
    in the metadata or errors when executing SQL statements against the 
    database. For brevity the examples below all omit the use of try/catch 
    blocks around the calls to the Relational DAS.
   </P
><P
>&#13;    These examples all differ from the expected use of SDO in two
    important respects.
   </P
><P
>&#13;    First, they show all interactions with the database completed within 
    one script. In this respect these scenarios are not realistic but are 
    chosen to illustrate just the use of the Relational DAS.
    It is expected that interactions with the database will be separated 
    in time and the data graph serialised and deserialised into the PHP 
    session one or more times as the application interacts with an end user.
   </P
><P
>&#13;    Second, all queries executed against the database use hard-coded 
    queries with no variables substituted. In this case it is safe to 
    use the simple 
    <B
CLASS="function"
>executeQuery()</B
>
    call, and this is what the examples illustrate. 
    In practice, though, it is unlikely that the SQL statement is known 
    entirely ahead of time. In order to allow variables to be safely 
    substituted into the SQL queries, without running the risk of 
    injecting SQL with unknown effects, it is safer to use the 
    <B
CLASS="function"
>executePreparedQuery()</B
>
    which takes a prepared SQL statement containing placeholders
    and a list of values to be substituted. 
   </P
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="sdo.das.rel.metadata"
>Specifying the metadata</A
></H2
><P
>&#13;     This first long section describes in detail how the metadata describing 
     the database and the required SDO model is supplied to the 
     Relational DAS.
    </P
><P
>&#13;     When the constructor for the Relational DAS is invoked, it needs to be 
     passed several pieces of information. The bulk of the information, 
     passed as an associative array in the first argument to the constructor, 
     tells the Relational DAS what it needs to know about the relational 
     database. It describes the names of the tables, columns, primary keys 
     and foreign keys. It should be fairly easy to understand what is 
     required, and once written it can be placed in a php file and included 
     when needed. The remainder of the information, passed in the second 
     and third arguments to the constructor, tells the Relational DAS what 
     it needs to know about the relationships between objects and the shape 
     of the data graph; it ultimately determines how the data from the 
     database is to be normalised into a graph.
    </P
><DIV
CLASS="section"
><H3
CLASS="section"
><A
NAME="sdo.das.rel.metadata.database"
>Database metadata</A
></H3
><P
>&#13;      The first argument to the constructor describes the target 
      relational database.
     </P
><P
>&#13;      Each table is described by an associative array with up to four keys.
      <DIV
CLASS="informaltable"
><P
></P
><A
NAME="AEN204888"
></A
><TABLE
BORDER="1"
CLASS="CALSTABLE"
><COL><COL><THEAD
><TR
><TH
>Key</TH
><TH
>Value</TH
></TR
></THEAD
><TBODY
><TR
><TD
>name</TD
><TD
>The name of the table.</TD
></TR
><TR
><TD
>columns</TD
><TD
>&#13;           An array listing the names of the columns, in any order.
          </TD
></TR
><TR
><TD
>PK</TD
><TD
>The name of the column containing the primary key.</TD
></TR
><TR
><TD
>FK</TD
><TD
>An array with two entries, 'from' and 'to', which define 
           a column containing a foreign key, and a table to which the foreign
           key points. If there are no foreign keys in the table then the 
           'FK' entry does not need to be specified. Only one foreign key 
           can be specified. Only a foreign key pointing to the primary key 
           of a table can be specified.
          </TD
></TR
></TBODY
></TABLE
><P
></P
></DIV
>
     </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#FF8000">/*****************************************************************<br />* METADATA DEFINING THE DATABASE<br />******************************************************************/<br /></font><font color="#0000BB">$company_table </font><font color="#007700">= array (<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'name' </font><font color="#007700">=&gt; </font><font color="#DD0000">'company'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'columns' </font><font color="#007700">=&gt; array(</font><font color="#DD0000">'id'</font><font color="#007700">, </font><font color="#DD0000">'name'</font><font color="#007700">,&nbsp;&nbsp;</font><font color="#DD0000">'employee_of_the_month'</font><font color="#007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'PK' </font><font color="#007700">=&gt; </font><font color="#DD0000">'id'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'FK' </font><font color="#007700">=&gt; array (<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'from' </font><font color="#007700">=&gt; </font><font color="#DD0000">'employee_of_the_month'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'to' </font><font color="#007700">=&gt; </font><font color="#DD0000">'employee'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;),<br />&nbsp;&nbsp;&nbsp;&nbsp;);<br /></font><font color="#0000BB">$department_table </font><font color="#007700">= array (<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'name' </font><font color="#007700">=&gt; </font><font color="#DD0000">'department'</font><font color="#007700">, <br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'columns' </font><font color="#007700">=&gt; array(</font><font color="#DD0000">'id'</font><font color="#007700">, </font><font color="#DD0000">'name'</font><font color="#007700">, </font><font color="#DD0000">'location'</font><font color="#007700">, </font><font color="#DD0000">'number'</font><font color="#007700">, </font><font color="#DD0000">'co_id'</font><font color="#007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'PK' </font><font color="#007700">=&gt; </font><font color="#DD0000">'id'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'FK' </font><font color="#007700">=&gt; array (<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'from' </font><font color="#007700">=&gt; </font><font color="#DD0000">'co_id'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'to' </font><font color="#007700">=&gt; </font><font color="#DD0000">'company'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;);<br /></font><font color="#0000BB">$employee_table </font><font color="#007700">= array (<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'name' </font><font color="#007700">=&gt; </font><font color="#DD0000">'employee'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'columns' </font><font color="#007700">=&gt; array(</font><font color="#DD0000">'id'</font><font color="#007700">, </font><font color="#DD0000">'name'</font><font color="#007700">, </font><font color="#DD0000">'SN'</font><font color="#007700">, </font><font color="#DD0000">'manager'</font><font color="#007700">, </font><font color="#DD0000">'dept_id'</font><font color="#007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'PK' </font><font color="#007700">=&gt; </font><font color="#DD0000">'id'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'FK' </font><font color="#007700">=&gt; array (<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'from' </font><font color="#007700">=&gt; </font><font color="#DD0000">'dept_id'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'to' </font><font color="#007700">=&gt; </font><font color="#DD0000">'department'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;);<br /></font><font color="#0000BB">$database_metadata </font><font color="#007700">= array(</font><font color="#0000BB">$company_table</font><font color="#007700">, </font><font color="#0000BB">$department_table</font><font color="#007700">, </font><font color="#0000BB">$employee_table</font><font color="#007700">);<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
><P
>&#13;      This metadata corresponds to a relational database that might have 
      been defined to MySQL as:
     </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="sql"
>create table company (
   id integer auto_increment,
   name char(20),
   employee_of_the_month integer,
   primary key(id)
 );
 create table department (
   id integer auto_increment,
   name char(20),
   location char(10),
   number integer(3),
   co_id integer,
   primary key(id)
 );
 create table employee (
   id integer auto_increment,
   name char(20),
   SN char(4),
   manager tinyint(1),
   dept_id integer,
   primary key(id)
 );</PRE
></TD
></TR
></TABLE
><P
>&#13;     or to DB2 as:
     </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="sql"
>create table company ( \
    id integer not null generated by default as identity,  \
    name varchar(20), \
    employee_of_the_month integer, \
    primary key(id) )
create table department ( \
    id integer not null generated by default as identity, \
    name varchar(20), \
    location varchar(10), \
    number integer, \
    co_id integer, \
    primary key(id) )
create table employee ( \
    id integer not null generated by default as identity, \
    name varchar(20), \
    SN char(4), \
    manager smallint, \
    dept_id integer, \
    primary key(id) )</PRE
></TD
></TR
></TABLE
><P
>&#13;      Note that although in this example there are no foreign keys specified 
      to the database and so the database is not expected to enforce 
      referential integrity, the intention behind the
      <CODE
CLASS="varname"
>co_id</CODE
>
      column on the department table and the
      <CODE
CLASS="varname"
>dept_id</CODE
>
      column on the employee table is they should contain the primary key 
      of their containing company or department record, respectively.
      So these two columns are acting as foreign keys.
     </P
><P
>&#13;      There is a third foreign key in this example, that from the
      <CODE
CLASS="varname"
>employee_of_the_month</CODE
>
      column of the company record to a single row of the employee table.
      Note the difference in intent between this foreign key and the other 
      two. The
      <CODE
CLASS="varname"
>employee_of_the_month</CODE
>
      column represents a single-valued relationship: there can be only 
      one employee of the month for a given company.
      The
      <CODE
CLASS="varname"
>co_id</CODE
>
      and
      <CODE
CLASS="varname"
>dept_id</CODE
>
      columns represent multi-valued relationships: a company can contain 
      many departments and a department can contain many employees.
      This distinction will become evident when the remainder of the metadata 
      picks out the company-department and department-employee relationships 
      as containment relationships.
     </P
><P
>&#13;      There are a few simple rules to be followed when constructing the 
      database metadata:
     </P
><P
></P
><UL
><LI
><P
>&#13;        All tables must have primary keys, and the primary keys must be
        specified in the metadata. Without primary keys it is not possible 
        to keep track of object identities. As you can see from the SQL 
        statements that create the tables, primary keys can be 
        auto-generated, that is, generated and assigned by the database when
        a record is inserted. In this case the auto-generated primary key 
        is obtained from the database and inserted into the data object 
        immediately after the row is inserted into the database.
       </P
></LI
><LI
><P
>&#13;        It is not necessary to specify in the metadata all the columns 
        that exist in the database, only those that will be used. 
        For example, if the company table had another column that the 
        application did not want to access with SDO, this need not be 
        specified in the metadata. On the other hand it would have done 
        no harm to specify it: if specified in the metadata but never 
        retrieved, or assigned to by the application, then the unused column 
        will not affect anything.
       </P
></LI
><LI
><P
>&#13;        In the database metadata note that the foreign key definitions 
        identify not the destination column in the table which is pointed 
        to, but the table name itself. Strictly, the relational model 
        permits the destination of a foreign key to be a non-primary key.
        Only foreign keys that point to a primary key are useful for 
        constructing the SDO model, so the metadata specifies the table name.
        It is understood that the foreign key points to the primary key of 
        the given table.
       </P
></LI
></UL
><P
>&#13;      Given these rules, and given the SQL statements that define the 
      database, the database metadata should be easy to construct.
     </P
><DIV
CLASS="section"
><H4
CLASS="section"
><A
NAME="sdo.das.rel.metadata.database.model"
>What the Relational DAS does with the metadata</A
></H4
><P
>&#13;       The Relational DAS uses the database metadata to form most of the 
       SDO model. For each table in the database metadata, an SDO type 
       is defined. Each column which can represent a primitive value 
       (columns which are not defined as foreign keys) are added 
       as properties to the SDO type.
      </P
><P
>&#13;       All primitive properties are given a type of string in the SDO model, 
       regardless of their SQL type. When writing values back to the 
       database the Relational DAS will create SQL statements that treat 
       the values as strings, and the database will convert them to the 
       appropriate type.
      </P
><P
>&#13;       Foreign keys are interpreted in one of two ways, depending on the 
       metadata in the third argument to the constructor that defines
       the SDO containment relationships.
       A discussion of this is therefore deferred until the section on
       <A
HREF="ref.sdo.das.rel.html#sdo.das.rel.metadata.crels"
>&#13;        SDO containment relationships
       </A
>
       below.
      </P
></DIV
></DIV
><DIV
CLASS="section"
><H3
CLASS="section"
><A
NAME="sdo.das.rel.metadata.approottype"
>Specifying the application root type</A
></H3
><P
>&#13;      The second argument to the constructor is the application root type.
      The true root of each data graph is an object of a special root type 
      and all application data objects come somewhere below that. Of the 
      various application types in the SDO model, one has to be the 
      application type immediately below the root of the data graph.
      If there is only one table in the database metadata, the application 
      root type can be inferred, and this argument can be omitted.
     </P
></DIV
><DIV
CLASS="section"
><H3
CLASS="section"
><A
NAME="sdo.das.rel.metadata.crels"
>Specifying the SDO containment relationships</A
></H3
><P
>&#13;      The third argument to the constructor defines how the types in the 
      model are to be linked together to form a graph. It identifies the 
      parent-child relationships between the types which collectively form a 
      graph. The relationships need to be supported by foreign keys to be 
      found in the data, in a way shortly to be described.
     </P
><P
>&#13;      The metadata is an array containing one or more associative arrays, 
      each of which identifies a parent and a child. The example below shows 
      a parent-child relationship from company to department, and another 
      from department to employee. Each of these will become an SDO property 
      defining a multi-valued containment relationship in the SDO model.

     </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br />$department_containment </font><font color="#007700">= array( </font><font color="#DD0000">'parent' </font><font color="#007700">=&gt; </font><font color="#DD0000">'company'</font><font color="#007700">, </font><font color="#DD0000">'child' </font><font color="#007700">=&gt; </font><font color="#DD0000">'department'</font><font color="#007700">);<br /></font><font color="#0000BB">$employee_containment </font><font color="#007700">= array( </font><font color="#DD0000">'parent' </font><font color="#007700">=&gt; </font><font color="#DD0000">'department'</font><font color="#007700">, </font><font color="#DD0000">'child' </font><font color="#007700">=&gt; </font><font color="#DD0000">'employee'</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$SDO_containment_metadata </font><font color="#007700">= array(</font><font color="#0000BB">$department_containment</font><font color="#007700">, </font><font color="#0000BB">$employee_containment</font><font color="#007700">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
><P
>&#13;      Foreign keys in the database metadata are interpreted as properties 
      with either multi-valued containment relationships or single-valued 
      non-containment references, depending on whether they have a 
      corresponding SDO containment relationship specified in the metadata. 
      In the example here, the foreign keys from department to company (the 
      <CODE
CLASS="varname"
>co_id</CODE
>
      column in the department table)
      and from employee to department (the
      <CODE
CLASS="varname"
>dept_id</CODE
>
      column in the employee table) are interpreted as supporting the
      SDO containment relationships.
      Each containment relationship mentioned in the SDO containment relationships
      metadata must have a corresponding foreign key present in the
      database and defined in the database metadata. The values of the 
      foreign key columns for containment relationships do not appear in the 
      data objects, instead each is represented by a containment relationship 
      from the parent to the child. So the
      <CODE
CLASS="varname"
>co_id</CODE
>
      column in the department row in the database, for example, does not 
      appear as a property on the department type, but instead as a 
      containment relationship called
      <CODE
CLASS="varname"
>department</CODE
>
      on the company type.
      Note that the foreign key and the parent-child relationship appear to 
      have opposite senses: the foreign key points from the department to 
      the company, but the parent-child relationship points from company to 
      department.
     </P
><P
>&#13;      The third foreign key in this example, the
      <CODE
CLASS="varname"
>employee_of_the_month</CODE
>
      ,
      is handled differently.
      This is not mentioned in the SDO containment relationships metadata.
      As a consequence this is interpreted in the second way: it becomes 
      a single-valued non-containment reference on the company object, to
      which can be assigned references to SDO data objects of the employee 
      type. It does appear as a property on the company type. The way to 
      assign a value to it in the SDO data graph is to have a graph that 
      contains an employee object through the containment relationships, and 
      to assign the object to it. This is illustrated in the later examples 
      below.
     </P
></DIV
></DIV
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="sdo.das.rel.examples.one-table"
>One-table examples</A
></H2
><P
>&#13;     The following set of examples all use the Relational DAS to work with 
     a data graph containing just one application data object, a single 
     company and the data just to be found the company table. These examples 
     do not exercise the power of SDO or the Relational DAS and of course 
     the same result could be achieved more economically with direct SQL 
     statements but they are intended to illustrate how to work with the 
     Relational DAS.
    </P
><P
>&#13;     For this very simple scenario it would be possible to simplify the 
     database metadata to include just the company table - if that were done
     the second and third arguments to the constructor and the column 
     specifier used in the query example would become optional.
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN204955"
></A
><P
><B
>例 1. Creating a data object</B
></P
><P
>&#13;       The simplest example is that of creating a single data object and 
       writing it to the database. In this example a single company object 
       is created, its name is set to 'Acme', and the Relational DAS is 
       called to write the changes to the database. The company name is 
       set here using the property name method. See the
       <A
HREF="ref.sdo.html#sdo.examples"
>Examples</A
>
       section on the SDO extension for other ways of accessing the 
       properties of an object.
      </P
><P
>&#13;       Data objects can only be created when you have a data object to 
       start with, however. It is for that reason that the first call 
       to the Relational DAS here is to obtain a root object. This is 
       in effect how to ask for an empty data graph - the special root 
       object is the true root of the tree. The company data object is 
       then created with a call to
       <B
CLASS="function"
>createDataObject()</B
>
       on the root object. This creates the company data object and inserts 
       it in the graph by inserting into a multi-valued containment property 
       on the root object called 'company'.
      </P
><P
>&#13;       When the Relational DAS is called to apply the changes a simple 
       insert statement 'INSERT INTO company (name) VALUES ("Acme");' 
       will be constructed and executed. The auto-generated primary key 
       will be set into the data object and the change summary will be reset, 
       so that it would be possible to continue working with the same data 
       object, modify it, and apply the newer changes a second time.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Construct the DAS with the metadata<br /> ***************************************************************/<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Obtain a root object and create a company object underneath.<br /> * Make a simple change to the data object. <br /> ***************************************************************/<br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das&nbsp;&nbsp;</font><font color="#007700">-&gt; </font><font color="#0000BB">createRootDataObject</font><font color="#007700">();<br /></font><font color="#0000BB">$acme </font><font color="#007700">= </font><font color="#0000BB">$root </font><font color="#007700">-&gt; </font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'company'</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$acme</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">"Acme"</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Get a database connection and write the object to the database<br /> ***************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /></font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">, </font><font color="#0000BB">$root</font><font color="#007700">);<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN204964"
></A
><P
><B
>例 2. Retrieving a data object</B
></P
><P
>&#13;       In this example a single data object is retrieved from the database 
       - or possibly more than one if there is more than one company 
       called 'Acme'. For each company returned, the
       <CODE
CLASS="varname"
>name</CODE
>
       and
       <CODE
CLASS="varname"
>id</CODE
>
       properties are echoed.
      </P
><P
>&#13;       In this example the third argument to
       <B
CLASS="function"
>executeQuery()</B
>,
       the column specifier is needed as there are other tables in the 
       metadata with column names of
       <CODE
CLASS="varname"
>name</CODE
>
       and
       <CODE
CLASS="varname"
>id</CODE
>.
       If there were no possible ambiguity it could be omitted.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Construct the DAS with the metadata<br /> ***************************************************************/<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Get a database connection<br /> ***************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Issue a query to obtain a company object - possibly more if they exist<br /> ***************************************************************/<br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">executeQuery</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'select name, id from company where name="Acme"'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array(</font><font color="#DD0000">'company.name'</font><font color="#007700">, </font><font color="#DD0000">'company.id'</font><font color="#007700">) );&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Echo name and id <br /> ***************************************************************/<br /></font><font color="#007700">foreach (</font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">] as </font><font color="#0000BB">$company</font><font color="#007700">) {<br />&nbsp;&nbsp;&nbsp;&nbsp;echo </font><font color="#DD0000">"Company obtained from the database has name = " </font><font color="#007700">. <br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#0000BB">$company</font><font color="#007700">[</font><font color="#DD0000">'name'</font><font color="#007700">] . </font><font color="#DD0000">" and id " </font><font color="#007700">. </font><font color="#0000BB">$company</font><font color="#007700">[</font><font color="#DD0000">'id'</font><font color="#007700">] . </font><font color="#DD0000">"\n"</font><font color="#007700">;<br />}<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN204975"
></A
><P
><B
>例 3. Updating a data object</B
></P
><P
>&#13;       This example combines the previous two, in the sense that in order 
       to be updated the object must first be retrieved. The application 
       code reverses the company name (so 'Acme' becomes 'emcA') and then the
       changes are written back to the database in the same way that they 
       were when the object was created. Because the query searches for 
       the name both ways round the program can be run repeatedly to find 
       the company and reverse its name each time.
      </P
><P
>&#13;       In this example the same instance of the Relational DAS is reused 
       for the
       <B
CLASS="function"
>applyChanges()</B
>,
       as is the PDO database handle. This is quite alright; it also 
       alright to allow the previous instances to be garbage collected 
       and to obtain new instances. No state data regarding the graph 
       is held the Relational DAS once it has returned a data graph to 
       the application. All necessary data is either within the graph itself, 
       or can be reconstructed from the metadata.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Construct the DAS with the metadata<br /> ***************************************************************/<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Get a database connection<br /> ***************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Issue a query to obtain a company object - possibly more if they exist<br /> ***************************************************************/<br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">executeQuery</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'select name, id from company where name="Acme" or name="emcA"'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;array(</font><font color="#DD0000">'company.name'</font><font color="#007700">, </font><font color="#DD0000">'company.id'</font><font color="#007700">) );<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Alter the name of just the first company<br /> ***************************************************************/<br /></font><font color="#0000BB">$company </font><font color="#007700">= </font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">];<br />echo </font><font color="#DD0000">"obtained a company with name of " </font><font color="#007700">. </font><font color="#0000BB">$company</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">. </font><font color="#DD0000">"\n"</font><font color="#007700">;<br /></font><font color="#0000BB">$company</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#0000BB">strrev</font><font color="#007700">(</font><font color="#0000BB">$company</font><font color="#007700">-&gt;</font><font color="#0000BB">name</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Write the change back<br /> ***************************************************************/<br /></font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,</font><font color="#0000BB">$root</font><font color="#007700">);<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN204982"
></A
><P
><B
>例 4. Deleting a data object</B
></P
><P
>&#13;       Any companies called 'Acme' or its reverse 'emcA' are retrieved.
       They are then all deleted from the graph with unset.
      </P
><P
>&#13;       In this example they are all deleted in one go by unsetting the 
       containing property (the property defining the containment 
       relationship). It is also possible to delete them individually.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Construct the DAS with the metadata<br /> ***************************************************************/<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Get a database connection<br /> ***************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Issue a query to obtain a company object - possibly more if they exist<br /> ***************************************************************/<br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">executeQuery</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'select name, id from company where name="Acme" or name="emcA"'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;array(</font><font color="#DD0000">'company.name'</font><font color="#007700">, </font><font color="#DD0000">'company.id'</font><font color="#007700">) );<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Delete any companies found from the data graph<br /> ***************************************************************/<br /></font><font color="#007700">unset(</font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">]);<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Write the change(s) back<br /> ***************************************************************/<br /></font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,</font><font color="#0000BB">$root</font><font color="#007700">);<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
></DIV
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="sdo.das.rel.examples.two-table"
>Two-table examples</A
></H2
><P
>&#13;     The following set of examples all use two tables from the company 
     database: the company and department tables. These examples exercise 
     more of the function of the Relational DAS.
    </P
><P
>&#13;     In this series of examples a company and department are created, 
     retrieved, updated, and finally deleted. This illustrates the 
     lifecycle for a data graph containing more than one object. Note that 
     this example clears out the company and department tables at the start 
     so that the exact results of the queries can be known.
    </P
><P
>&#13;     You can find these examples combined into one script called
     <TT
CLASS="filename"
>1cd-CRUD</TT
>
     in the
     <TT
CLASS="filename"
>Scenarios</TT
>
     directory in the Relational DAS package.
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN204995"
></A
><P
><B
>例 5. One company, one department - Create</B
></P
><P
>&#13;       As in the earlier example of creating just one company data object, 
       the first action after constructing the Relational DAS is to call
       <B
CLASS="function"
>createRootDataObject()</B
>
       to obtain the special root object of the otherwise empty data graph.
       The company object is then created as a child of the root object, 
       and the department object as a child of the company object.
      </P
><P
>&#13;       When it comes to applying the changes, the Relational DAS has to 
       perform special processing to maintain the foreign keys that support 
       the containment relationships, especially if auto-generated primary 
       keys are involved. In this example, the relationship between the 
       auto-generated primary key 
       <CODE
CLASS="varname"
>id</CODE
>
       in the company table and the
       <CODE
CLASS="varname"
>co_id</CODE
>
       column in the department table must be maintained. When inserting a 
       company and department for the first time the Relational DAS has to 
       first insert the company row, then call PDO's
       <B
CLASS="function"
>getLastInsertId()</B
>
       method to obtain the auto-generated primary key, then add that as 
       the value of the
       <CODE
CLASS="varname"
>co_id</CODE
>
       column when inserting the department row.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/*************************************************************************************<br />* Empty out the two tables<br />*************************************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /></font><font color="#0000BB">$pdo_stmt </font><font color="#007700">= </font><font color="#0000BB">$dbh</font><font color="#007700">-&gt;</font><font color="#0000BB">prepare</font><font color="#007700">(</font><font color="#DD0000">'DELETE FROM COMPANY;'</font><font color="#007700">);<br /></font><font color="#0000BB">$rows_affected </font><font color="#007700">= </font><font color="#0000BB">$pdo_stmt</font><font color="#007700">-&gt;</font><font color="#0000BB">execute</font><font color="#007700">();<br /></font><font color="#0000BB">$pdo_stmt </font><font color="#007700">= </font><font color="#0000BB">$dbh</font><font color="#007700">-&gt;</font><font color="#0000BB">prepare</font><font color="#007700">(</font><font color="#DD0000">'DELETE FROM DEPARTMENT;'</font><font color="#007700">);<br /></font><font color="#0000BB">$rows_affected </font><font color="#007700">= </font><font color="#0000BB">$pdo_stmt</font><font color="#007700">-&gt;</font><font color="#0000BB">execute</font><font color="#007700">();<br /><br /></font><font color="#FF8000">/**************************************************************<br />* Create a company with name Acme and one department, the Shoe department<br />***************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">createRootDataObject</font><font color="#007700">();<br /><br /></font><font color="#0000BB">$acme </font><font color="#007700">= </font><font color="#0000BB">$root </font><font color="#007700">-&gt; </font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'company'</font><font color="#007700">);<br /></font><font color="#0000BB">$acme </font><font color="#007700">-&gt; </font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">"Acme"</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$shoe </font><font color="#007700">= </font><font color="#0000BB">$acme</font><font color="#007700">-&gt;</font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'department'</font><font color="#007700">);<br /></font><font color="#0000BB">$shoe</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">'Shoe'</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">, </font><font color="#0000BB">$root</font><font color="#007700">);<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN205006"
></A
><P
><B
>例 6. One company, one department - Retrieve and Update</B
></P
><P
>&#13;       In this case the SQL query passed to
       <B
CLASS="function"
>executeQuery()</B
>
       performs an inner join to join the data from the company 
       and department tables. Primary keys for both the company and 
       department tables must be included in the query. The result set 
       is re-normalised to form a normalised data graph. Note that a 
       column specifier is passed as the third argument to the 
       <B
CLASS="function"
>executeQuery()</B
>
       call enabling the Relational DAS to know which column is which in 
       the result set.
      </P
><P
>&#13;       Note that the
       <CODE
CLASS="varname"
>co_id</CODE
>
       column although used in the query is not needed in the result set.
       In order to understand what the Relational DAS is doing when it builds 
       the data graph it may be helpful to visualise what the result set 
       looks like. Although the data in the database is normalised, so that 
       multiple department rows can point through their foreign key to one 
       company row, the data in the result set is non-normalised: that is, 
       if there is one company and multiple departments, the values for the 
       company are repeated in each row. The Relational DAS has to reverse 
       this process and turn the result set back into a normalised data graph, 
       with just one company object.
      </P
><P
>&#13;       In this example the Relational DAS will examine the result set and 
       column specifier, find data for both the company and department 
       tables, find primary keys for both, and interpret each row as 
       containing data for a department and its parent company. If it has 
       not seen data for that company before (it uses the primary key to 
       check) it creates a company object and then a department object 
       underneath it. If it has seen data for that company before and 
       has already created the company object it just creates the 
       department object underneath.
      </P
><P
>&#13;       In this way the Relational DAS can retrieve and renormalise data 
       for multiple companies and multiple departments underneath them.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Retrieve the company and Shoe department, then delete Shoe and add IT<br /> ***************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">executeQuery</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,<br /></font><font color="#DD0000">'select c.id, c.name, d.id, d.name from company c, department d where d.co_id = c.id'</font><font color="#007700">,<br />array(</font><font color="#DD0000">'company.id'</font><font color="#007700">,</font><font color="#DD0000">'company.name'</font><font color="#007700">,</font><font color="#DD0000">'department.id'</font><font color="#007700">,</font><font color="#DD0000">'department.name'</font><font color="#007700">));<br /><br /></font><font color="#0000BB">$acme </font><font color="#007700">= </font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#FF8000">// get the first company - will be 'Acme'<br /></font><font color="#0000BB">$shoe </font><font color="#007700">= </font><font color="#0000BB">$acme</font><font color="#007700">[</font><font color="#DD0000">'department'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#FF8000">// get the first department underneath - will be 'Shoe'<br /><br /></font><font color="#007700">unset(</font><font color="#0000BB">$acme</font><font color="#007700">[</font><font color="#DD0000">'department'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">]);<br /><br /></font><font color="#0000BB">$it </font><font color="#007700">= </font><font color="#0000BB">$acme</font><font color="#007700">-&gt;</font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'department'</font><font color="#007700">);<br /></font><font color="#0000BB">$it</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">'IT'</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">, </font><font color="#0000BB">$root</font><font color="#007700">);<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN205017"
></A
><P
><B
>例 7. One company, two departments - Retrieve and Delete</B
></P
><P
>&#13;       In this example the company and department are retrieved and 
       then deleted. It is not necessary to delete them individually 
       (although that would be possible) - deleting the company object 
       from the data graph also deletes any departments underneath it.
      </P
><P
>&#13;       Note the way that the company object is actually deleted using the 
       PHP unset call. The unset has to be performed on the containing 
       property which in this case is 
       the company property on the special 
       root object. You must use:
       <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">unset(</font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">]);<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
>
       and not:
       <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">unset(</font><font color="#0000BB">$acme</font><font color="#007700">); </font><font color="#FF8000">//WRONG<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
>
       Simply unsetting
       <CODE
CLASS="varname"
>$acme</CODE
>
       would destroy the variable but leave the data in the data 
       graph untouched.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/**************************************************************<br /> * Retrieve the company and IT department, then delete the whole company<br /> ***************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">executeQuery</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,<br /></font><font color="#DD0000">'select c.id, c.name, d.id, d.name from company c, department d where d.co_id = c.id'</font><font color="#007700">,<br />array(</font><font color="#DD0000">'company.id'</font><font color="#007700">,</font><font color="#DD0000">'company.name'</font><font color="#007700">,</font><font color="#DD0000">'department.id'</font><font color="#007700">,</font><font color="#DD0000">'department.name'</font><font color="#007700">));<br /><br /></font><font color="#0000BB">$acme </font><font color="#007700">= </font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">];<br /></font><font color="#0000BB">$it </font><font color="#007700">= </font><font color="#0000BB">$acme</font><font color="#007700">[</font><font color="#DD0000">'department'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">];<br /><br />unset(</font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">]);<br /><br /></font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">, </font><font color="#0000BB">$root</font><font color="#007700">);<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
></DIV
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="sdo.das.rel.examples.three-table"
>Three-table example</A
></H2
><P
>&#13;     The following examples use all three tables from the company database: 
     the company, department, and employee tables. These introduce the final 
     piece of function not exercised by the examples above: the 
     non-containment reference
     <CODE
CLASS="varname"
>employee_of_the_month</CODE
>.
    </P
><P
>&#13;     Like the examples above for company and department, this set of examples 
     is intended to illustrate the full lifecycle of such a data graph.
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN205031"
></A
><P
><B
>例 8. One company, one department, one employee - Create</B
></P
><P
>&#13;       In this example a company is created containing one department and 
       just one employee. Note that this example clears out all three tables 
       at the start so that the exact results of the queries can be known.
      </P
><P
>&#13;       Note how once the company, department and employee have been created, 
       the
       <CODE
CLASS="varname"
>employee_of_the_month</CODE
>
       property of the company can be made to point at the new employee.
       As this is a non-containment reference, this cannot be done until 
       the employee object has been created within the graph.
       Non-containment references need to be managed carefully.
       For example if the employee were now deleted from under the department, 
       it would not be correct to try to save the graph without
       first clearing or re-assigning the
       <CODE
CLASS="varname"
>employee_of_the_month</CODE
>
       property.
       The closure rule for SDO data graphs requires that any object pointed 
       at by a non-containment reference must also be reachable by 
       containment relationships.
      </P
><P
>&#13;       When it comes to inserting the graph into the database, the procedure 
       is similar to the example of inserting the company and department,
       but
       <CODE
CLASS="varname"
>employee_of_the_month</CODE
>
       introduces an extra complexity.
       The Relational DAS needs to insert the objects working down the tree 
       formed by containment relationships, so company, then department, then 
       employee. This is necessary so that it always has the auto-generated 
       primary key of a parent on hand to include in a child row. But when 
       the company row is inserted the employee who is employee of the month 
       has not yet been inserted and the primary key is not known. The 
       procedure is that after the employee record is inserted and its 
       primary key known, a final step is performed in which the the 
       company record is updated with the employee's primary key.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/*************************************************************************************<br />* Empty out the three tables<br />*************************************************************************************/<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /></font><font color="#0000BB">$pdo_stmt </font><font color="#007700">= </font><font color="#0000BB">$dbh</font><font color="#007700">-&gt;</font><font color="#0000BB">prepare</font><font color="#007700">(</font><font color="#DD0000">'DELETE FROM COMPANY;'</font><font color="#007700">);<br /></font><font color="#0000BB">$rows_affected </font><font color="#007700">= </font><font color="#0000BB">$pdo_stmt</font><font color="#007700">-&gt;</font><font color="#0000BB">execute</font><font color="#007700">();<br /></font><font color="#0000BB">$pdo_stmt </font><font color="#007700">= </font><font color="#0000BB">$dbh</font><font color="#007700">-&gt;</font><font color="#0000BB">prepare</font><font color="#007700">(</font><font color="#DD0000">'DELETE FROM DEPARTMENT;'</font><font color="#007700">);<br /></font><font color="#0000BB">$rows_affected </font><font color="#007700">= </font><font color="#0000BB">$pdo_stmt</font><font color="#007700">-&gt;</font><font color="#0000BB">execute</font><font color="#007700">();<br /></font><font color="#0000BB">$pdo_stmt </font><font color="#007700">= </font><font color="#0000BB">$dbh</font><font color="#007700">-&gt;</font><font color="#0000BB">prepare</font><font color="#007700">(</font><font color="#DD0000">'DELETE FROM EMPLOYEE;'</font><font color="#007700">);<br /></font><font color="#0000BB">$rows_affected </font><font color="#007700">= </font><font color="#0000BB">$pdo_stmt</font><font color="#007700">-&gt;</font><font color="#0000BB">execute</font><font color="#007700">();<br /><br /></font><font color="#FF8000">/*************************************************************************************<br />* Create a tiny but complete company.<br />* The company name is Acme.<br />* There is one department, Shoe.<br />* There is one employee, Sue.<br />* The employee of the month is Sue.<br />*************************************************************************************/<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$root &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$das&nbsp;&nbsp;</font><font color="#007700">-&gt; </font><font color="#0000BB">createRootDataObject</font><font color="#007700">();<br /></font><font color="#0000BB">$acme &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$root </font><font color="#007700">-&gt; </font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'company'</font><font color="#007700">);<br /></font><font color="#0000BB">$acme </font><font color="#007700">-&gt; </font><font color="#0000BB">name &nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#DD0000">"Acme"</font><font color="#007700">;<br /></font><font color="#0000BB">$shoe &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$acme </font><font color="#007700">-&gt; </font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'department'</font><font color="#007700">);<br /></font><font color="#0000BB">$shoe </font><font color="#007700">-&gt; </font><font color="#0000BB">name &nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#DD0000">'Shoe'</font><font color="#007700">;<br /></font><font color="#0000BB">$shoe </font><font color="#007700">-&gt; </font><font color="#0000BB">location </font><font color="#007700">= </font><font color="#DD0000">'A-block'</font><font color="#007700">;<br /></font><font color="#0000BB">$sue &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$shoe </font><font color="#007700">-&gt; </font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'employee'</font><font color="#007700">);<br /></font><font color="#0000BB">$sue </font><font color="#007700">-&gt; </font><font color="#0000BB">name &nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#DD0000">'Sue'</font><font color="#007700">;<br /></font><font color="#0000BB">$acme </font><font color="#007700">-&gt; </font><font color="#0000BB">employee_of_the_month </font><font color="#007700">= </font><font color="#0000BB">$sue</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">, </font><font color="#0000BB">$root</font><font color="#007700">);<br /><br />echo </font><font color="#DD0000">"Wrote back Acme with one department and one employee\n"</font><font color="#007700">;<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN205041"
></A
><P
><B
>例 9. One company, one department, one employee - Retrieve and update</B
></P
><P
>&#13;       The SQL statement passed to the Relational DAS is this time an inner 
       join that retrieves data from all three tables. Otherwise this example 
       introduces nothing that has not appeared in a previous example. 
      </P
><P
>&#13;       The graph is updated by the addition of a new department and employee 
       and some alterations to the name properties of the existing objects 
       in the graph. The combined changes are then written back. The 
       Relational DAS will process and apply an arbitrary mixture of 
       additions, modifications and deletions to and from the data graph.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/*************************************************************************************<br /> * Find the company again and change various aspects.<br /> * Change the name of the company, department and employee.<br /> * Add a second department and a new employee.<br /> * Change the employee of the month.<br /> *************************************************************************************/<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">executeQuery</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">"select c.id, c.name, c.employee_of_the_month, d.id, d.name, e.id, e.name " </font><font color="#007700">.<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">"from company c, department d, employee e " </font><font color="#007700">.<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">"where e.dept_id = d.id and d.co_id = c.id and c.name='Acme'"</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array(</font><font color="#DD0000">'company.id'</font><font color="#007700">,</font><font color="#DD0000">'company.name'</font><font color="#007700">,</font><font color="#DD0000">'company.employee_of_the_month'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'department.id'</font><font color="#007700">,</font><font color="#DD0000">'department.name'</font><font color="#007700">,</font><font color="#DD0000">'employee.id'</font><font color="#007700">,</font><font color="#DD0000">'employee.name'</font><font color="#007700">));<br /></font><font color="#0000BB">$acme &nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">];<br /><br /></font><font color="#0000BB">$shoe&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$acme</font><font color="#007700">-&gt;</font><font color="#0000BB">department</font><font color="#007700">[</font><font color="#0000BB">0</font><font color="#007700">];<br /></font><font color="#0000BB">$sue&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$shoe </font><font color="#007700">-&gt; </font><font color="#0000BB">employee</font><font color="#007700">[</font><font color="#0000BB">0</font><font color="#007700">];<br /><br /></font><font color="#0000BB">$it &nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$acme</font><font color="#007700">-&gt;</font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'department'</font><font color="#007700">);<br /></font><font color="#0000BB">$it</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">'IT'</font><font color="#007700">;<br /></font><font color="#0000BB">$it</font><font color="#007700">-&gt;</font><font color="#0000BB">location </font><font color="#007700">= </font><font color="#DD0000">'G-block'</font><font color="#007700">;<br /></font><font color="#0000BB">$billy &nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#0000BB">$it</font><font color="#007700">-&gt;</font><font color="#0000BB">createDataObject</font><font color="#007700">(</font><font color="#DD0000">'employee'</font><font color="#007700">);<br /></font><font color="#0000BB">$billy</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">'Billy'</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$acme</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">'MegaCorp'</font><font color="#007700">;<br /></font><font color="#0000BB">$shoe</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">'Footwear'</font><font color="#007700">;<br /></font><font color="#0000BB">$sue</font><font color="#007700">-&gt;</font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#DD0000">'Susan'</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$acme</font><font color="#007700">-&gt;</font><font color="#0000BB">employee_of_the_month </font><font color="#007700">= </font><font color="#0000BB">$billy</font><font color="#007700">;<br /></font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">, </font><font color="#0000BB">$root</font><font color="#007700">);<br />echo </font><font color="#DD0000">"Wrote back company with extra department and employee and all the names changed (Megacorp/Footwear/Susan)\n"</font><font color="#007700">;<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
><P
>&#13;     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN205047"
></A
><P
><B
>例 10. One company, two departments, two employees - Retrieve and delete</B
></P
><P
>&#13;       The company is retrieved as a complete data graph containing five 
       data objects - the company, two departments and two employees.
       They are all deleted by deleting the company object. Deleting an 
       object from the graph deletes all the object beneath it in the graph.
       Five SQL DELETE statements will be generated and  executed. As always 
       they will be qualified with a WHERE clause that contains all of the 
       fields that were retrieved, so that any updates to the data in the 
       database in the meantime by another process will be detected.
      </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">require_once </font><font color="#DD0000">'SDO/DAS/Relational.php'</font><font color="#007700">;<br />require_once </font><font color="#DD0000">'company_metadata.inc.php'</font><font color="#007700">;<br /><br /></font><font color="#FF8000">/*************************************************************************************<br /> * Now read it one more time and delete it.<br /> * You can delete part, apply the changes, then carry on working with the same graph but<br /> * care is needed to keep closure - you cannot delete the employee who is eotm without<br /> * reassigning. For safety here we delete the company all in one go. <br /> *************************************************************************************/<br /></font><font color="#0000BB">$das </font><font color="#007700">= new </font><font color="#0000BB">SDO_DAS_Relational </font><font color="#007700">(</font><font color="#0000BB">$database_metadata</font><font color="#007700">,</font><font color="#DD0000">'company'</font><font color="#007700">,</font><font color="#0000BB">$SDO_containment_metadata</font><font color="#007700">);<br /></font><font color="#0000BB">$dbh </font><font color="#007700">= new </font><font color="#0000BB">PDO</font><font color="#007700">(</font><font color="#0000BB">PDO_DSN</font><font color="#007700">,</font><font color="#0000BB">DATABASE_USER</font><font color="#007700">,</font><font color="#0000BB">DATABASE_PASSWORD</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$root </font><font color="#007700">= </font><font color="#0000BB">$das</font><font color="#007700">-&gt;</font><font color="#0000BB">executeQuery</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">"select c.id, c.name, c.employee_of_the_month, d.id, d.name, e.id, e.name " </font><font color="#007700">.<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">"from company c, department d, employee e " </font><font color="#007700">.<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">"where e.dept_id = d.id and d.co_id = c.id and c.name='MegaCorp';"</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array(</font><font color="#DD0000">'company.id'</font><font color="#007700">,</font><font color="#DD0000">'company.name'</font><font color="#007700">,</font><font color="#DD0000">'company.employee_of_the_month'</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#DD0000">'department.id'</font><font color="#007700">,</font><font color="#DD0000">'department.name'</font><font color="#007700">,</font><font color="#DD0000">'employee.id'</font><font color="#007700">,</font><font color="#DD0000">'employee.name'</font><font color="#007700">));<br /></font><font color="#0000BB">$megacorp </font><font color="#007700">= </font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">][</font><font color="#0000BB">0</font><font color="#007700">];<br /><br />unset(</font><font color="#0000BB">$root</font><font color="#007700">[</font><font color="#DD0000">'company'</font><font color="#007700">]);<br /></font><font color="#0000BB">$das </font><font color="#007700">-&gt; </font><font color="#0000BB">applyChanges</font><font color="#007700">(</font><font color="#0000BB">$dbh</font><font color="#007700">, </font><font color="#0000BB">$root</font><font color="#007700">);<br /><br />echo </font><font color="#DD0000">"Deleted the company, departments and employees all in one go.\n"</font><font color="#007700">;<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
    </P
></DIV
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="sdo.das.rel.tracing"
>Tracing</A
></H1
><P
>&#13;    You may be interested in seeing the SQL statements that are generated 
    in order to apply changes back to the database. At the top of the
    <TT
CLASS="filename"
>SDO/DAS/Relational.php</TT
>
    you will find a number of constants which control whether the process 
    of constructing and executing the SQL statements is to be traced.
    Try setting
    <CODE
CLASS="varname"
>DEBUG_EXECUTE_PLAN</CODE
>
    to <TT
CLASS="constant"
><B
>TRUE</B
></TT
> to see the generated SQL statements.
   </P
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="sdo.das.rel.classes"
>预定义类</A
></H1
><P
>&#13;    The Relational DAS provides two classes: the Relational DAS itself and 
    the subclass of Exception that can be thrown. The Relational DAS has 
    four publicly useful calls: the constructor,
    the
    <B
CLASS="function"
>createRootDataObject()</B
>
    call to obtain the root object of an empty data graph,
    the
    <B
CLASS="function"
>executeQuery()</B
>
    call to obtain a data graph containing data from a relational database,
    and the
    <B
CLASS="function"
>applyChanges()</B
>
    call to write changes made to a data graph back to the relational 
    database.
   </P
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="sdo.das.rel.sdo-das-relational"
><B
CLASS="classname"
>SDO_DAS_Relational</B
></A
></H2
><P
>&#13;     The only object other than an SDO_DAS_Relational_Exception with which 
     the application is expected to interact.
    </P
><DIV
CLASS="section"
><H3
CLASS="section"
><A
NAME="sdo.das.rel.sdo-das-relational.methods"
>方法</A
></H3
><P
></P
><UL
><LI
><P
>&#13;        <A
HREF="function.sdo-das-relational-construct.html"
>&#13;         __construct
        </A
> 
        - construct the Relational DAS with a model derived from the 
        passed metadata
       </P
></LI
><LI
><P
>&#13;        <A
HREF="function.sdo-das-relational-createrootdataobject.html"
>&#13;         createRootDataObject
        </A
> 
        - obtain an otherwise empty data graph containing just the special 
        root object
       </P
></LI
><LI
><P
>&#13;        <A
HREF="function.sdo-das-relational-executequery.html"
>&#13;         executeQuery
        </A
>
        - execute an SQL query passed as a literal string and return  
        the results as a normalised data graph
       </P
></LI
><LI
><P
>&#13;        <A
HREF="function.sdo-das-relational-executepreparedquery.html"
>&#13;         executePreparedQuery
        </A
>
        - execute an SQL query passed as a prepared statement, with a 
        list of values to substitute for placeholders, and return the 
        results as a normalised data graph
       </P
></LI
><LI
><P
>&#13;        <A
HREF="function.sdo-das-relational-applychanges.html"
>&#13;         applyChanges
        </A
>
        - examine the change summary in the data graph and apply those 
        changes back to the database, subject to an assumption 
        of optimistic concurrency
       </P
></LI
></UL
></DIV
></DIV
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="sdo.das.rel.sdo-das-relational-exception"
><B
CLASS="classname"
>SDO_DAS_Relational_Exception</B
></A
></H2
><P
>&#13;     Is a subclass of PHP's
     <B
CLASS="classname"
>Exception</B
>.
     It adds no behaviour to
     <B
CLASS="classname"
>Exception</B
>.
     Thrown, with useful descriptive text, to signal errors in the 
     metadata or unexpected failures to perform SQL operations.
    </P
></DIV
></DIV
></DIV
><DIV
CLASS="TOC"
><DL
><DT
><B
>目录</B
></DT
><DT
><A
HREF="function.sdo-das-relational-applychanges.html"
>SDO_DAS_Relational::applyChanges</A
>&nbsp;--&nbsp;
	    Applies the changes made to a data graph back to the database.
  </DT
><DT
><A
HREF="function.sdo-das-relational-construct.html"
>SDO_DAS_Relational::__construct</A
>&nbsp;--&nbsp;
	    Creates an instance of a Relational Data Access Service
  </DT
><DT
><A
HREF="function.sdo-das-relational-createrootdataobject.html"
>SDO_DAS_Relational::createRootDataObject</A
>&nbsp;--&nbsp;
   Returns the special root object in an otherwise 
   empty data graph. Used when creating a data graph from scratch.
  </DT
><DT
><A
HREF="function.sdo-das-relational-executepreparedquery.html"
>SDO_DAS_Relational::executePreparedQuery</A
>&nbsp;--&nbsp;
   Executes an SQL query passed as a prepared statement, with a 
   list of values to substitute for placeholders, and return the 
   results as a normalised data graph.
  </DT
><DT
><A
HREF="function.sdo-das-relational-executequery.html"
>SDO_DAS_Relational::executeQuery</A
>&nbsp;--&nbsp;
	    Executes a given SQL query against a relational database 
        and returns the results as a normalised data graph.
  </DT
></DL
></DIV
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="function.sdo-das-xml-savestring.html"
ACCESSKEY="P"
>上一页</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>起始页</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="function.sdo-das-relational-applychanges.html"
ACCESSKEY="N"
>下一页</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>SDO_DAS_XML::saveString</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="funcref.html"
ACCESSKEY="U"
>上一级</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>SDO_DAS_Relational::applyChanges</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>