Skip to content

Commit d8b4f17

Browse files
committed
More doc on objects
1 parent 75e189d commit d8b4f17

File tree

6 files changed

+222
-121
lines changed

6 files changed

+222
-121
lines changed

doc/api.md

Lines changed: 205 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,15 @@ For installation information, see the [Node-oracledb Installation Instructions][
432432
- 20.6 [Binding Multiple Values to a SQL `WHERE IN` Clause](#sqlwherein)
433433
- 20.7 [Binding Column and Table Names in Queries](#sqlbindtablename)
434434
21. [Oracle Database Objects and Collections](#objects)
435+
- 21.1 [Inserting Objects](#objectinsert)
436+
- 21.2 [Fetching Objects](#objectfetch)
437+
- 21.3 [PL/SQL Collection Types](#plsqlcollections)
438+
- 21.3.1 [PL/SQL Collection Associative Arrays (Index-by)](#plsqlindexbybinds)
439+
- 21.3.2 [PL/SQL Collection VARRAY Types](#plsqlvarray)
440+
- 21.3.3 [PL/SQL Collection Nested Tables](#plsqlnestedtables)
441+
- 21.4 [PL/SQL RECORD Types](#plsqlrecords)
442+
- 21.5 [Inserting or Passing Multiple Objects of the Same Type](#objexecmany)
443+
- 21.6 [Oracle Database Object Type Limitations](#objectlimitations)
435444
22. [Batch Statement Execution with `executeMany()`](#batchexecution)
436445
23. [Transaction Management](#transactionmgt)
437446
24. [Statement Caching](#stmtcache)
@@ -11031,7 +11040,7 @@ multiple hard-coded SQL statements, each with a different ORDER BY.
1103111040
You can query and insert most Oracle Database objects and collections,
1103211041
with some [limitations](#objectlimitations).
1103311042
11034-
### Inserting Objects
11043+
### <a name="objectinsert"></a> 21.1 Inserting Objects
1103511044
1103611045
As an example, the Oracle Spatial type [SDO_GEOMETRY][139] can easily
1103711046
be used in node-oracledb. Describing SDO_GEOMETRY in SQL*Plus shows:
@@ -11174,7 +11183,7 @@ connection.close({drop: true})`](#connectionclose), or restart the
1117411183
pool. Then `getDbObjectClass()` can be called again to get the
1117511184
updated type information.
1117611185
11177-
### Fetching Objects
11186+
### <a name="objectfetch"></a> 21.2 Fetching Objects
1117811187
1117911188
When objects are fetched, they are represented as a
1118011189
[DbObject](#dbobjectclass):
@@ -11221,7 +11230,7 @@ For DbObjects representing Oracle collections, methods such as
1122111230
1122211231
```javascript
1122311232
console.log(o.SDO_ELEM_INFO.getKeys()); // [ 0, 1, 2 ]
11224-
console.log(o.SDO_ELEM_INFO.getValues()); // [ 1, 1003, 3 ]
11233+
console.log(o.SDO_ELEM_INFO.getValues()); // [ 1, 1003, 3 ]
1122511234
```
1122611235
1122711236
The options [`fetchAsBuffer`](#propdbfetchasbuffer) and
@@ -11233,117 +11242,13 @@ LOBs will be fetched as [Lob objects](#lobclass). The
1123311242
the data. Note it is an asynchronous method and requires a round-trip
1123411243
to the database.
1123511244
11236-
### <a name="plsqlrecords"></a> PL/SQL RECORD Types
11245+
### <a name="plsqlcollections"></a> 21.3 PL/SQL Collection Types
1123711246
11238-
PL/SQL RECORDS can be bound for insertion and retrieval. Given the
11239-
PL/SQL package:
11247+
PL/SQL has three collection types: associative arrays, VARRAY
11248+
(variable-size arrays), and nested tables. See [Collection
11249+
Types][150] in the Database PL/SQL Language Reference.
1124011250
11241-
```sql
11242-
CREATE OR REPLACE PACKAGE seachange AS
11243-
TYPE shiptype IS RECORD (shipname VARCHAR2(40), weight NUMBER);
11244-
PROCEDURE biggership (p_in IN shiptype, p_out OUT shiptype);
11245-
END seachange;
11246-
11247-
CREATE OR REPLACE PACKAGE BODY seachange AS
11248-
PROCEDURE biggership (p_in IN shiptype, p_out OUT shiptype) AS
11249-
BEGIN
11250-
p_out := p_in;
11251-
p_out.weight := p_out.weight * 2;
11252-
END;
11253-
END seachange;
11254-
```
11255-
11256-
You can get a prototype object for the SHIPTYPE record by calling
11257-
`getDbObjectClass()` and then create a new object `vessel` for a ship.
11258-
This can be bound for input when calling the BIGGERSHIP procedure. To
11259-
retrieve a SHIPTYPE record back from the database, pass the prototype
11260-
object class for the output bind `type`:
11261-
11262-
```javascript
11263-
ShipTypeClass = await connection.getDbObjectClass("SEACHANGE.SHIPTYPE");
11264-
11265-
vessel = new ShipTypeClass({ SHIPNAME: 'BoatFace', WEIGHT: 1200 });
11266-
11267-
binds = {
11268-
inbv: vessel,
11269-
outbv: { type: ShipTypeClass, dir: oracledb.BIND_OUT }
11270-
};
11271-
11272-
result = await connection.execute(`CALL seachange.biggership(:inbv, :outbv)`, binds);
11273-
console.log(result.outBinds.outbv.SHIPNAME, result.outBinds.outbv.WEIGHT);
11274-
```
11275-
11276-
The output shows the increased ship size:
11277-
11278-
```
11279-
BoatFace 2400
11280-
```
11281-
11282-
See [plsqlrecord.js][147] for a runnable example.
11283-
11284-
### <a name="objvarray"></a> Working with VARRAY Types
11285-
11286-
Given a table with a VARRAY column:
11287-
11288-
```sql
11289-
CREATE TYPE playertype AS OBJECT (
11290-
shirtnumber NUMBER,
11291-
name VARCHAR2(20));
11292-
11293-
CREATE TYPE teamtype AS VARRAY(10) OF playertype;
11294-
11295-
CREATE TABLE sports (sportname VARCHAR2(20), team teamtype);
11296-
```
11297-
11298-
You can insert values using:
11299-
11300-
```javascript
11301-
TeamTypeClass = await connection.getDbObjectClass("TEAMTYPE");
11302-
11303-
hockeyTeam = new TeamTypeClass(
11304-
[
11305-
{SHIRTNUMBER: 11, NAME: 'Elizabeth'},
11306-
{SHIRTNUMBER: 22, NAME: 'Frank'},
11307-
]
11308-
);
11309-
11310-
await connection.execute(
11311-
`INSERT INTO sports (sportname, team) VALUES (:sn, :t)`,
11312-
{
11313-
sn: "Hockey",
11314-
t: hockeyTeam
11315-
});
11316-
```
11317-
11318-
Querying the table could be done like:
11319-
11320-
```javascript
11321-
result = await connection.execute(
11322-
`SELECT sportname, team FROM sports`,
11323-
[],
11324-
{
11325-
outFormat: oracledb.OUT_FORMAT_OBJECT
11326-
}
11327-
);
11328-
for (row of result.rows) {
11329-
console.log("The " + row.SPORTNAME + " team players are:");
11330-
for (const player of row.TEAM) {
11331-
console.log(" " + player.NAME);
11332-
}
11333-
}
11334-
```
11335-
11336-
The output would be:
11337-
11338-
```
11339-
The Hockey team players are:
11340-
Elizabeth
11341-
Frank
11342-
```
11343-
11344-
See [selectvarray.js][146] for a runnable example.
11345-
11346-
### <a name="plsqlindexbybinds"></a> PL/SQL Collection Associative Arrays (Index-by)
11251+
#### <a name="plsqlindexbybinds"></a> 21.3.1 PL/SQL Collection Associative Arrays (Index-by)
1134711252
1134811253
Arrays of strings and numbers can be bound to PL/SQL IN, IN OUT, and
1134911254
OUT parameters of PL/SQL INDEX BY associative array types with integer
@@ -11364,6 +11269,7 @@ Given this table and PL/SQL package:
1136411269
1136511270
```sql
1136611271
DROP TABLE mytab;
11272+
1136711273
CREATE TABLE mytab (id NUMBER, numcol NUMBER);
1136811274

1136911275
CREATE OR REPLACE PACKAGE mypkg IS
@@ -11496,12 +11402,195 @@ Parameters](#executebindParams) for more information about binding.
1149611402
1149711403
See [plsqlarray.js][58] for a runnable example.
1149811404
11499-
### Inserting or Passing Multiple Objects of the Same Type
11405+
#### <a name="plsqlvarray"></a> 21.3.2 PL/SQL Collection VARRAY Types
11406+
11407+
Given a table with a VARRAY column:
11408+
11409+
```sql
11410+
CREATE TYPE playertype AS OBJECT (
11411+
shirtnumber NUMBER,
11412+
name VARCHAR2(20));
11413+
/
11414+
11415+
CREATE TYPE teamtype AS VARRAY(10) OF playertype;
11416+
/
11417+
11418+
CREATE TABLE sports (sportname VARCHAR2(20), team teamtype);
11419+
```
11420+
11421+
You can insert values using:
11422+
11423+
```javascript
11424+
await connection.execute(
11425+
`INSERT INTO sports (sportname, team) VALUES (:sn, :t)`,
11426+
{
11427+
sn: "Hockey",
11428+
t:
11429+
{
11430+
type: "TEAMTYPE",
11431+
val:
11432+
[
11433+
{SHIRTNUMBER: 11, NAME: 'Georgia'},
11434+
{SHIRTNUMBER: 22, NAME: 'Harriet'}
11435+
]
11436+
}
11437+
}
11438+
);
11439+
11440+
// Alternatively:
11441+
11442+
TeamTypeClass = await connection.getDbObjectClass("TEAMTYPE");
11443+
11444+
hockeyTeam = new TeamTypeClass(
11445+
[
11446+
{SHIRTNUMBER: 22, NAME: 'Elizabeth'},
11447+
{SHIRTNUMBER: 33, NAME: 'Frank'},
11448+
]
11449+
);
11450+
11451+
await connection.execute(
11452+
`INSERT INTO sports (sportname, team) VALUES (:sn, :t)`,
11453+
{
11454+
sn: "Hockey",
11455+
t: hockeyTeam
11456+
});
11457+
11458+
```
11459+
11460+
Querying the table could be done like:
11461+
11462+
```javascript
11463+
result = await connection.execute(
11464+
`SELECT sportname, team FROM sports`,
11465+
[],
11466+
{
11467+
outFormat: oracledb.OUT_FORMAT_OBJECT
11468+
}
11469+
);
11470+
for (row of result.rows) {
11471+
console.log("The " + row.SPORTNAME + " team players are:");
11472+
for (const player of row.TEAM) {
11473+
console.log(" " + player.NAME);
11474+
}
11475+
}
11476+
```
11477+
11478+
The output would be:
11479+
11480+
```
11481+
The Hockey team players are:
11482+
Elizabeth
11483+
Frank
11484+
```
11485+
11486+
See [selectvarray.js][146] for a runnable example.
11487+
11488+
#### <a name="plsqlnestedtables"></a> 21.3.3 PL/SQL Collection Nested Tables
11489+
11490+
Given a nested table `staffList`:
11491+
11492+
```sql
11493+
CREATE TABLE bonuses (id NUMBER, name VARCHAR2(20));
11494+
11495+
CREATE OR REPLACE PACKAGE personnel AS
11496+
TYPE staffList IS TABLE OF bonuses%ROWTYPE;
11497+
PROCEDURE awardBonuses (goodStaff staffList);
11498+
END personnel;
11499+
/
11500+
11501+
CREATE OR REPLACE PACKAGE BODY personnel AS
11502+
PROCEDURE awardBonuses (goodStaff staffList) IS
11503+
BEGIN
11504+
FORALL i IN INDICES OF goodStaff
11505+
INSERT INTO bonuses (id, name) VALUES (goodStaff(i).id, goodStaff(i).name);
11506+
END;
11507+
END;
11508+
/
11509+
```
11510+
11511+
you can call `awardBonuses()` like:
11512+
11513+
```javascript
11514+
plsql = `CALL personnel.awardBonuses(:gsbv)`;
11515+
11516+
binds = {
11517+
gsbv:
11518+
{
11519+
type: "PERSONNEL.STAFFLIST",
11520+
val:
11521+
[
11522+
{ID: 1, NAME: 'Chris' },
11523+
{ID: 2, NAME: 'Sam' }
11524+
]
11525+
}
11526+
};
11527+
11528+
await connection.execute(plsql, binds);
11529+
```
11530+
11531+
Similar with other objects, calling
11532+
[`getDbObjectClass()`](#getdbobjectclass) and using a constructor to
11533+
create a `DbObject` for binding can also be used.
11534+
11535+
### <a name="plsqlrecords"></a> 21.4 PL/SQL RECORD Types
11536+
11537+
PL/SQL RECORDS can be bound for insertion and retrieval. This example
11538+
uses the PL/SQL package:
11539+
11540+
```sql
11541+
CREATE OR REPLACE PACKAGE seachange AS
11542+
TYPE shiptype IS RECORD (shipname VARCHAR2(40), weight NUMBER);
11543+
PROCEDURE biggership (p_in IN shiptype, p_out OUT shiptype);
11544+
END seachange;
11545+
/
11546+
11547+
CREATE OR REPLACE PACKAGE BODY seachange AS
11548+
PROCEDURE biggership (p_in IN shiptype, p_out OUT shiptype) AS
11549+
BEGIN
11550+
p_out := p_in;
11551+
p_out.weight := p_out.weight * 2;
11552+
END;
11553+
END seachange;
11554+
/
11555+
```
11556+
11557+
Similar to previous examples, you can use a prototype DbObject from
11558+
`getdbobjectclass()` for binding, or pass an Oracle type name.
11559+
11560+
Below a prototype object for the SHIPTYPE record is returned from
11561+
`getDbObjectClass()` and then a new object `vessel` is created for a
11562+
ship. This is bound for input when calling the BIGGERSHIP procedure.
11563+
To retrieve a SHIPTYPE record back from the the PL/SQL, the prototype
11564+
object class is passed for the output bind `type`:
11565+
11566+
```javascript
11567+
ShipTypeClass = await connection.getDbObjectClass("SEACHANGE.SHIPTYPE");
11568+
11569+
vessel = new ShipTypeClass({ SHIPNAME: 'BoatFace', WEIGHT: 1200 });
11570+
11571+
binds = {
11572+
inbv: vessel,
11573+
outbv: { type: ShipTypeClass, dir: oracledb.BIND_OUT }
11574+
};
11575+
11576+
result = await connection.execute(`CALL seachange.biggership(:inbv, :outbv)`, binds);
11577+
console.log(result.outBinds.outbv.SHIPNAME, result.outBinds.outbv.WEIGHT);
11578+
```
11579+
11580+
The output shows the increased ship size:
11581+
11582+
```
11583+
BoatFace 2400
11584+
```
11585+
11586+
See [plsqlrecord.js][147] for a runnable example.
11587+
11588+
### <a name="objexecmany"></a> 21.5 Inserting or Passing Multiple Objects of the Same Type
1150011589
1150111590
You can use `executeMany()` with objects. See [Binding Objects with
1150211591
`executeMany()`](#executemanyobjects).
1150311592
11504-
### <a name="objectlimitations"></a> Oracle Database Object Type Limitations
11593+
### <a name="objectlimitations"></a> 21.6 Oracle Database Object Type Limitations
1150511594
1150611595
PL/SQL collections and records can only be bound when both Oracle
1150711596
client libraries and Oracle Database are 12.1, or higher.
@@ -11798,6 +11887,7 @@ CREATE OR REPLACE PACKAGE rectest AS
1179811887
TYPE rectype IS RECORD (name VARCHAR2(40), pos NUMBER);
1179911888
PROCEDURE myproc (p_in IN rectype, p_out OUT rectype);
1180011889
END rectest;
11890+
/
1180111891
```
1180211892
1180311893
This can be called like:
@@ -13900,3 +13990,4 @@ When upgrading from node-oracledb version 3.1 to version 4.0:
1390013990
[147]: https://github.com/oracle/node-oracledb/tree/master/examples/plsqlrecord.js
1390113991
[148]: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-C4C426FC-FD23-4B2E-8367-FA5F83F3F23A
1390213992
[149]: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-4848E6A0-58A7-44FD-8D6D-A033D0CCF9CB
13993+
[150]: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7E9034D5-0D33-43A1-9012-918350FE148C

0 commit comments

Comments
 (0)