Oracle9i Application Developer's Guide - Large Objects (LOBs) Release 2 (9.2) Part Number A96591-01 |
|
This chapter describes each operation on LOBs (such as "Write Data to a LOB") in terms of a use case. Table 10-1, "Internal Persistent LOB Basic Operations", alphabetically lists all these use cases.
Each detailed internal persistent LOB use case operation description is laid out as follows:
Table 10-1, indicates with a + where examples are provided for specific use cases in each programmatic environment. An "S" indicates that SQL is used for that use case and applicable programmatic environment(s).
We refer to programmatic environments by means of the following abbreviations:
LOB Use Case | P | O | CP | B | C | V | J |
---|---|---|---|---|---|---|---|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
+ |
+ |
- |
+ |
+ |
- |
+ |
|
- |
+ |
- |
- |
- |
- |
- |
|
- |
+ |
- |
- |
- |
- |
- |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
Closing LOBs - see Chapter 3, "LOB Support in Different Programmatic Environments" |
- |
- |
- |
- |
- |
- |
- |
+ |
- |
- |
+ |
+ |
+ |
+ |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
S |
S |
- |
S |
S |
S |
S |
|
Creating a Table Containing an Object Type with a LOB Attribute |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
|
Creating a Varray Containing References to LOBs See Chapter 5, "Large Objects: Advanced Topics" |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
S |
|
- |
+ |
- |
+ |
+ |
+ |
- |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
- |
- |
- |
+ |
+ |
+ |
- |
|
- |
+ |
- |
- |
+ |
- |
+ |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
- |
+ |
- |
+ |
+ |
- |
- |
|
Initialized Locator: Checking If a LOB Locator Is Initialized |
- |
+ |
- |
- |
+ |
- |
- |
S |
S |
S |
S |
S |
S |
+ |
|
S |
+ |
- |
+ |
+ |
+ |
+ |
|
S |
S |
S |
S |
S |
S |
S |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
Loading an Internal Persistent BLOB with Binary Data from a BFILE |
+ |
- |
- |
- |
- |
- |
- |
+ |
- |
- |
- |
- |
- |
- |
|
S |
S |
S |
S |
S |
S |
S |
|
+ |
+ |
- |
- |
- |
- |
- |
|
+ |
+ |
- |
+ |
+ |
- |
+ |
|
Opening LOBs - see Chapter 3, "LOB Support in Different Programmatic Environments" |
- |
- |
- |
- |
- |
- |
- |
+ |
- |
- |
+ |
+ |
- |
+ |
|
+ |
- |
- |
+ |
+ |
+ |
+ |
|
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
Streaming LOB Data. See "JDBC: New LOB Streaming APIs" . Note: This API has not yet been incorporated in this chapter as a use case. See a forthcoming release. |
- |
- |
- |
- |
- |
- |
+ |
+ |
+ |
- |
+ |
+ |
+ |
+ |
|
S |
S |
S |
S |
S |
S |
S |
|
S |
S |
S |
S |
S |
S |
S |
|
S |
+ |
- |
+ |
+ |
+ |
+ |
|
Write-Append, see Append-Writing to the End of a LOB . |
- |
- |
- |
- |
- |
- |
- |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
This procedure describes how to create a table containing one or more LOB columns.
When you use functions, EMPTY_BLOB
() and EMPTY_CLOB
(), the resulting LOB is initialized, but not populated with data. LOBs that are empty are not null, and vice versa. This is discussed in more detail in "Inserting a LOB Value using EMPTY_CLOB() or EMPTY_BLOB()".
When creating tables that contain LOBs use the guidelines and examples described in the following:
See Also:
Oracle9i SQL Reference for a complete specification of syntax for using |
Use the following syntax reference:
These examples use the following Oracle9i Sample Schemas:
You must create the HR and OE schemas before your create the PM schema. For details on these schemas, you must refer to Oracle9i Sample Schemas.
How to create a table containing a LOB column is illustrated with the following example, in SQL:
You may need to set up the following data structures for certain examples in this manual to work.
Note: Since you can use SQL DDL directly to create a table containing one or more |
/* Setup script for creating Print_media, Online_media and associated structures */ DROP USER pm CASCADE; DROP DIRECTORY ADPHOTO_DIR; DROP DIRECTORY ADCOMPOSITE_DIR; DROP DIRECTORY ADGRAPHIC_DIR; DROP INDEX onlinemedia CASCADE CONSTRAINTS; DROP INDEX printmedia CASCADE CONSTRAINTS; DROP TABLE online_media CASCADE CONSTRAINTS; DROP TABLE print_media CASCADE CONSTRAINTS; DROP TYPE textdoc_typ; DROP TYPE textdoc_tab; DROP TYPE adheader_typ; DROP TABLE adheader_typ; CREATE USER pm; GRANT CONNECT, RESOURCE to pm; CREATE DIRECTORY ADPHOTO_DIR AS '/tmp/'; CREATE DIRECTORY ADCOMPOSITE_DIR AS '/tmp/'; CREATE DIRECTORY ADGRAPHIC_DIR AS '/tmp/'; CREATE DIRECTORY media_dir AS '/tmp/'; GRANT READ ON DIRECTORY ADPHOTO_DIR to pm; GRANT READ ON DIRECTORY ADCOMPOSITE_DIR to pm; GRANT READ ON DIRECTORY ADGRAPHIC_DIR to pm; GRANT READ ON DIRECTORY media_dir to pm; CONNECT pm/pm (or &pass); COMMIT; CREATE TABLE a_table (blob_col BLOB); CREATE TYPE adheader_typ AS OBJECT ( header_name VARCHAR2(256), creation_date DATE, header_text VARCHAR(1024), logo BLOB ); CREATE TYPE textdoc_typ AS OBJECT ( document_typ VARCHAR2(32), formatted_doc BLOB); CREATE TYPE Textdoc_ntab AS TABLE of textdoc_typ; CREATE TABLE adheader_tab of adheader_typ ( Ad_finaltext DEFAULT EMPTY_CLOB(), CONSTRAINT Take CHECK (Take IS NOT NULL), DEFAULT NULL); CREATE TABLE online_media ( product_id NUMBER(6), product_photo ORDSYS.ORDImage, product_photo_signature ORDSYS.ORDImageSignature, product_thumbnail ORDSYS.ORDImage, product_video ORDSYS.ORDVideo, product_audio ORDSYS.ORDAudio, product_text CLOB, product_testimonials ORDSYS.ORDDoc); CREATE UNIQUE INDEX onlinemedia_pk ON online_media (product_id); ALTER TABLE online_media ADD (CONSTRAINT onlinemedia_pk PRIMARY KEY (product_id), CONSTRAINT loc_c_id_fk FOREIGN KEY (product_id) REFERENCES oe.product_information(product_id) ); CREATE TABLE print_media (product_id NUMBER(6), ad_id NUMBER(6), ad_composite BLOB, ad_sourcetext CLOB, ad_finaltext CLOB, ad_fktextn NCLOB, ad_testdocs_ntab textdoc_tab, ad_photo BLOB, ad_graphic BFILE, ad_header adheader_typ, press_release LONG) NESTED TABLE ad_textdocs_ntab STORE AS textdocs_nestedtab; CREATE UNIQUE INDEX printmedia_pk ON print_media (product_id, ad_id); ALTER TABLE print_media ADD (CONSTRAINT printmedia_pk PRIMARY KEY (product_id, ad_id), CONSTRAINT printmedia_fk FOREIGN KEY (product_id) REFERENCES oe.product_information(product_id) );
This procedure describes how to create a table containing an object type with a LOB attribute.
When creating tables that contain LOBs use the guidelines and examples described in the following:
See the following specific reference for a detailed syntax description:
You must create the object type that contains LOB attributes before you can proceed to create a table that makes use of that object type.
This example uses the Product Media schema included with Oracle9i sample schemas. For details on this schema, you must refer to the Oracle9i Sample Schemas manual.
This example is provided in SQL and applies to all programmatic environments:
Create adheader_typ
as a basis for tables containing ad headings or titles and logos used in these examples:
CREATE TYPE adheader_typ AS OBJECT ( header_name VARCHAR2(256), creation_date DATE, header_text VARCHAR(1024), logo BLOB ); /* Create table adheader_tab Using SQL DDL: */ CREATE TABLE adheader_tab of adheader_typ ( logo DEFAULT EMPTY_BLOB() CONSTRAINT Take CHECK (Take IS NOT NULL), creation_date DATE );
Create Type adheader_typ
using SQL DDL as a basis for a table that will contain the column object:
DROP TYPE adheader; DROP TABLE adheader_tab; CREATE TYPE adheader_typ AS OBJECT ( header_name VARCHAR2(256), creation_date DATE, header_text VARCHAR(1024), logo BLOB ); /* Create support table adheader_tab as an archive of ad headers using SQL DDL: */ CREATE TABLE adheader_tab of adheader_typ;
See Also:
Oracle9i SQL Reference for a complete specification of the syntax for using |
This procedure creates a nested table containing a LOB.
When creating tables that contain LOBs use the guidelines and examples described in the following sections and these chapters:
Use the following syntax reference:
Create the object type that contains the LOB attributes before you create a nested table based on that object type. In our example, table Print_media
contains nested table ad_textdoc_ntab
that has type textdoc_tab
. This type uses two LOB datatypes:
We have already described how to create a table with LOB columns in the previous section (see "Creating a Table Containing One or More LOB Columns"), so here we only describe the syntax for creating the underlying object type.
The example "SQL: Creating a Nested Table Containing a LOB" is provided in the SQL programmatic environment.
/* Create type textdoc_typ as the base type for the nested table textdoc_ntab, where textdoc_ntab contains a LOB: */ DROP TYPE textdoc_typ force; DROP TYPE textdoc_ntab; DROP TABLE textdoc_ntable; CREATE TYPE textdoc_typ AS OBJECT ( document_typ VARCHAR2(32), formatted_doc BLOB ); /* The type has been created. Now you need a */ /* nested table of that type to embed in */ /* table Print_media, so: */ CREATE TYPE textdoc_ntab AS TABLE of textdoc_typ; CREATE TABLE textdoc_ntable ( id number, textdoc_ntab textdoc_typ) NESTED TABLE textdoc_ntab STORE AS textdoc_nestedtab;
The actual embedding of the nested table is accomplished when the structure of the containing table is defined. In our example, this is effected by the NESTED TABLE
statement when the Print_media
table is created.
This procedure describes how to insert a LOB value using EMPTY_CLOB() or EMPTY_BLOB().
Here are guidelines for inserting LOBs:
Before you write data to an internal LOB
, make the LOB
column non-null; that is, the LOB column must contain a locator that points to an empty or populated LOB
value. You can initialize a BLOB
column's value by using the function EMPTY_BLOB
() as a default predicate. Similarly, a CLOB
or NCLOB
column's value can be initialized by using the function EMPTY_CLOB
().
You can also initialize a LOB column with a character or raw string less than 4,000 bytes in size. For example:
INSERT INTO Print_media (product_id, ad_id, ad_sourcetext) VALUES (1, 1, 'This is a One Line Advertisement');
You can perform this initialization during CREATE
TABLE
(see "Creating a Table Containing One or More LOB Columns") or, as in this case, by means of an INSERT
.
For guidelines on how to INSERT into a LOB when binds of more than 4,000 bytes are involved, see the following sections in Chapter 7, "Modeling and Design":
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
See Also:
Oracle9i Sample Schemas for a description of the PM Schema and the |
Examples are provided in the following programmatic environments:
These functions are special functions in Oracle SQL, and are not part of the DBMS_LOB
package.
/* In the new row of table Print_media, the columns ad_sourcetext and ad_fltextn are initialized using EMPTY_CLOB(), the columns ad_composite and ad_photo are initialized using EMPTY_BLOB(), the column formatted-doc in the nested table is initialized using EMPTY_ BLOB(), the column logo in the column object is initialized using EMPTY_BLOB(): */ INSERT INTO Print_media VALUES (3060,11001, EMPTY_BLOB(), EMPTY_CLOB(),EMPTY_CLOB(),EMPTY_CLOB(), textdoc_tab(textdoc_typ ('HTML', EMPTY_BLOB())), EMPTY_BLOB(), NULL, adheader_typ('any header name', <any date>, 'ad header text goes here', EMPTY_BLOB()), 'Press release goes here');
This procedure describes how to insert a row containing a LOB as SELECT.
For example, assuming Print_media
and Online_media
have identical schemas. The statement creates a new LOB
locator in table Print_media. It also
copies the LOB
data from Online_media
to the location pointed to by the new LOB
locator inserted in table Print_media
.
For guidelines on how to INSERT into a LOB when binds of more than 4,000 bytes are involved, see the following sections in Chapter 7, "Modeling and Design":
Use the following syntax reference:
For LOBs, one of the advantages of using an object-relational approach is that you can define a type as a common template for related tables. For instance, it makes sense that both the tables that store archival material and working tables that use those libraries, share a common structure.
The following code fragment is based on the fact that the table Online_media
is of the same type as Print_media
referenced by the ad_textdocs_ntab
column of table Print_media
. It inserts values into the library table, and then inserts this same data into Print_media
by means of a SELECT
.
See Also:
Oracle9i Sample Schemas for a description of the PM Schema and the |
The following example is provided in SQL and applies to all the programmatic environments:
/* Store records in the archive table Online_media: */ INSERT INTO Online_media VALUES (3060, NULL, NULL, NULL, NULL, 'some text about this CRT Monitor', NULL); /* Insert values into Print_media by selecting from Online_media: */ INSERT INTO Print_media (product_id, ad_id, ad_sourcetext) (SELECT product_id, 11001, product_text FROM Online_media where product_id = 3060);
This procedure inserts a row by initializing a LOB locator bind variable.
For guidelines on how to INSERT and UPDATE a LOB when binds of more than 4,000 bytes are involved, see the following sections in Chapter 7, "Modeling and Design":
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
In the following examples you use a LOB
locator bind variable to take ad_photo
data in one row of Print_media
and insert it into another row.
Examples are provided in the following programmatic environments:
/* Note that the example procedure insertUseBindVariable_proc is not part of the DBMS_LOB package. */ CREATE OR REPLACE PROCEDURE insertUseBindVariable_proc (productnum IN NUMBER, adnum IN NUMBER, Blob_loc IN BLOB) IS BEGIN INSERT INTO Print_media (product_id, ad_id, ad_photo) VALUES (productnum, adnum, Blob_loc); END; DECLARE Blob_loc BLOB; BEGIN /* Select the LOB from the row where product_id = 3106 and ad_id=13001. Initialize the LOB locator bind variable: */ SELECT ad_photo INTO Blob_loc FROM Print_media WHERE product_id = 3106 AND ad_id=13001; /* Insert into the row where product_id = 2056 AND ad_id=12001 */ insertUseBindVariable_proc (2056, 12001, Blob_loc); COMMIT; END;
/* Select the locator into a locator variable */ sb4 select_Printmedia_Locator (Lob_loc, errhp, stmthp, svchp) OCILobLocator *Lob_loc; OCIError *errhp; OCIStmt *stmthp; OCISvcCtx *svchp; { OCIDefine *defnp1, *defnp2; text *sqlstmt = (text *)"SELECT ad_photo FROM Print_media WHERE product_id=2268 AND ad_ id=21001"; /* Prepare the SQL statement */ checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Define the column being selected */ checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2)SQLT_BLOB,(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp2, errhp, (ub4) 2, (dvoid *)&Lob_loc, (sb4)0, (ub2)SQLT_BLOB,(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT)); /* Execute and fetch one row */ checkerr (errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return (0); } /* Insert the selected Locator into table using Bind Variables. This function selects a locator from the Print_media table and inserts it into the same table in another row. */ void insertUseBindVariable (envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { int clipid; OCILobLocator *Lob_loc; OCIBind *bndhp2; OCIBind *bndhp1; text *insstmt = (text *) "INSERT INTO Print_media (product_id, ad_photo) VALUES (:2268, :3060)"; /* Allocate locator resources */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select a LOB locator from the Print_media table */ select_Printmedia_Locator(Lob_loc, errhp, stmthp, svchp); /* Insert the locator into the Print_media table with product_id=3060 */ product_id = 3060; /* Prepare the SQL statement */ checkerr (errhp, OCIStmtPrepare(stmthp, errhp, insstmt, (ub4) strlen((char *) insstmt), (ub4) OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Binds the bind positions */ checkerr (errhp, OCIBindByPos(stmthp, &bndhp1, errhp, (ub4) 1, (dvoid *) &clipid, (sb4) sizeof(clipid), SQLT_INT, (dvoid *) 0, (ub2 *)0, (ub2 *)0, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIBindByPos(stmthp, &bndhp2, errhp, (ub4) 2, (dvoid *) &Lob_loc, (sb4) 0, SQLT_BLOB, (dvoid *) 0, (ub2 *)0, (ub2 *)0, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT)); /* Execute the SQL statement */ checkerr (errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); /* Free LOB resources*/ OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB);
IDENTIFICATION DIVISION. PROGRAM-ID. INSERT-LOB. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 BLOB1 SQL-BLOB. 01 USERID PIC X(11) VALUES "PM/PM". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. INSERT-LOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Initialize the BLOB locator EXEC SQL ALLOCATE :BLOB1 END-EXEC. * Populate the LOB EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_PHOTO INTO :BLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 2268 AND AD_ID = 21001 END-EXEC. * Insert the value with PRODUCT_ID of 3060 EXEC SQL INSERT INTO PRINT_MEDIA (PRODUCT_ID, AD_PHOTO) VALUES (3060, 11001, :BLOB1)END-EXEC. * Free resources held by locator END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
#include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void insertUseBindVariable_proc(Rownum, Lob_loc) int Rownum, Rownum2; OCIBlobLocator *Lob_loc; { EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL INSERT INTO Print_media (product_id, ad_id, ad_photo) VALUES (:Rownum, :Rownum2, :Lob_loc); } void insertBLOB_proc() { OCIBlobLocator *Lob_loc; /* Initialize the BLOB Locator: */ EXEC SQL ALLOCATE :Lob_loc; /* Select the LOB from the row where product_id = 2268 and ad_id=21001: */ EXEC SQL SELECT ad_photo INTO :Lob_loc FROM Print_media WHERE product_id = 2268 AND ad_id = 21001; /* Insert into the row where product_id = 3106 and ad_id = 13001: */ insertUseBindVariable_proc(3106, 13001, Lob_loc); /* Release resources held by the locator: */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "pm/pm"; EXEC SQL CONNECT :pm; insertBLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
Dim OraDyn as OraDynaset, OraPhoto1 as OraBLOB, OraPhotoClone as OraBLOB Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id", ORADYN_DEFAULT) Set OraPhoto1 = OraDyn.Fields("ad_photo").Value 'Clone it for future reference Set OraPhotoClone = OraPhoto1 'Go to Next row OraDyn.MoveNext 'Lets update the current row and set the LOB to OraPhotoClone OraDyn.Edit Set OraPhoto1 = OraPhotoClone OraDyn.Update
// Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_31 { public static void main (String args []) throws Exception { // Load the Oracle JDBC driver DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver ()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { ResultSet rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 3106 AND ad_id = 13001"); if (rset.next()) { // retrieve the LOB locator from the ResultSet BLOB adphoto_blob = ((OracleResultSet)rset).getBLOB (1); OraclePreparedStatement ops = (OraclePreparedStatement) conn.prepareStatement( "INSERT INTO Print_media (product_id, ad_id, ad_photo) VALUES (2268, 21001, ?)"); ops.setBlob(1, adphoto_blob); ops.execute(); conn.commit(); conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to load a LOB with data from a BFILE.
Note: The |
Since LOB
s can be quite large in size, it makes sense that SQL*Loader can load LOB
data from either the main datafile (that is, in-line with the rest of the data) or from one or more secondary datafiles.
To load LOB
data from the main datafile, the usual SQL*Loader formats can be used. LOB
data instances can be in predetermined size fields, delimited fields, or length-value pair fields.
For detailed information and tips on using SQL Loader for loading data into an internal LOB see "Loading Inline LOB Data" and "Loading Out-Of-Line LOB Data" in Chapter 4 of this guide.
In using OCI, or any of the programmatic environments that access OCI functionality, character set conversions are implicitly performed when translating from one character set to another. When you use the DBMS_LOB.LOADFROMFILE procedure to populate a CLOB or NCLOB, you are populating the LOB with binary data from the BFILE. No implicit translation is performed from binary data to a character set. For this reason, you should use the LOADCLOBFROMFILE procedure when loading text (see Loading an Internal Persistent CLOB with BFILE Data on).
Unless you specify maxlobsize
to load the entire BFILE, the amount (the number of bytes) you specify to load from a BFILE must be less than or equal to the size of BFILE as follows:
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The examples assume that there is an operating system source file keyboard_3106_13001
that contains LOB data to be loaded into the target LOB ad_composite
. The examples also assume that directory object ADVERT_DIR
already exists and is mapped to the location of the source file.
Examples are provided in the following programmatic environments:
/* Loading a LOB with Data from a BFILE. Note that the example procedure loadLOBFromBFILE_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE loadLOBFromBFILE_proc IS Dest_loc BLOB; Src_loc BFILE := BFILENAME('ADPHOTO_DIR', 'keyboard_3106_13001'); Amount INTEGER := 4000; BEGIN SELECT ad_photo INTO Dest_loc FROM print_media WHERE product_id = 3106 and ad_id=13001 FOR UPDATE; /* Opening the source BFILE is mandatory: */ DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY); /* Opening the LOB is optional: */ DBMS_LOB.OPEN(Dest_loc, DBMS_LOB.LOB_READWRITE); DBMS_LOB.LOADFROMFILE(Dest_loc, Src_loc, Amount); /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE(Dest_loc); DBMS_LOB.CLOSE(Src_loc); COMMIT; END;
/* Selecting a BLOB from Print_media and loading it with data from a BFILE */ sb4 select_lock_adphoto_locator_3(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_photo FROM Print_media WHERE product_id=2056 AND ad_id = 12001 FOR UPDATE"; OCIDefine *defnp1, *defnp2; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) OCIDefineByPos(stmthp, &defnp2, errhp, (ub4) 2, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } void LoadLobDataFromBFile(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *bfile; OCILobLocator *blob; ub4 amount= 4000; /* Allocate the Source (bfile) & destination (blob) locators desriptors*/ OCIDescriptorAlloc((dvoid *)envhp, (dvoid **)&bfile, (ub4)OCI_DTYPE_FILE, (size_t)0, (dvoid **)0); OCIDescriptorAlloc((dvoid *)envhp, (dvoid **)&blob, (ub4)OCI_DTYPE_LOB, (size_t)0, (dvoid **)0); /* Select a ad_photo locator for update */ printf (" select the ad_photo locator...\n"); select_lock_adphoto_locator_2056(blob, errhp, svchp, stmthp); /* Set the Directory Alias and File Name of the ad_photo file */ printf (" set the file name in bfile\n"); checkerr (errhp, OCILobFileSetName(envhp, errhp, &bfile, (text*)"ADPHOTO_DIR", (ub2)strlen("ADPHOTO_DIR"), (text*)"mousepad_2056_12001", (ub2)strlen("mousepad_2056_12001"))); printf (" open the bfile\n"); /* Opening the BFILE locator is Mandatory */ checkerr (errhp, (OCILobOpen(svchp, errhp, bfile, OCI_LOB_READONLY))); printf(" open the lob\n"); /* Opening the BLOB locator is optional */ checkerr (errhp, (OCILobOpen(svchp, errhp, blob, OCI_LOB_READWRITE))); /* Load the data from the graphic file (bfile) into the blob */ printf (" load the LOB from File\n"); checkerr (errhp, OCILobLoadFromFile(svchp, errhp, blob, bfile, (ub4)amount, (ub4)1, (ub4)1)); /* Closing the LOBs is Mandatory if they have been Opened */ checkerr (errhp, OCILobClose(svchp, errhp, bfile)); checkerr (errhp, OCILobClose(svchp, errhp, blob)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) bfile, (ub4) OCI_DTYPE_FILE); (void) OCIDescriptorFree((dvoid *) blob, (ub4) OCI_DTYPE_LOB); return; }
IDENTIFICATION DIVISION. PROGRAM-ID. LOB-LOAD. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 DEST SQL-BLOB. 01 BFILE1 SQL-BFILE. 01 DIR-ALIAS PIC X(30) VARYING. 01 FNAME PIC X(20) VARYING. * Declare the amount to load. The value here * was chosen arbitrarily 01 LOB-AMT PIC S9(9) COMP VALUE 10. 01 USERID PIC X(11) VALUES "PM/PM". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. LOB-LOAD. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BFILE locator EXEC SQL ALLOCATE :BFILE1 END-EXEC. * Set up the directory and file information MOVE "ADGRAPHIC_DIR" TO DIR-ALIAS-ARR. MOVE 9 TO DIR-ALIAS-LEN. MOVE "keyboard_3106_13001" TO FNAME-ARR. MOVE 16 TO FNAME-LEN. EXEC SQL LOB FILE SET :BFILE1 DIRECTORY = :DIR-ALIAS,FILENAME = :FNAME END-EXEC. * Allocate and initialize the destination BLOB EXEC SQL ALLOCATE :DEST END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_GRAPHIC INTO :DEST FROM PRINT_MEDIA WHERE PRODUCT_ID = 2268 AND AD_ID = 21001 FOR UPDATE END-EXEC. * Open the source BFILE for READ EXEC SQL LOB OPEN :BFILE1 READ ONLY END-EXEC. * Open the destination BLOB for READ/WRITE EXEC SQL LOB OPEN :DEST READ WRITE END-EXEC. * Load the destination BLOB from the source BFILE EXEC SQL LOB LOAD :LOB-AMT FROM FILE :BFILE1 INTO :DEST END-EXEC. * Close the source and destination LOBs EXEC SQL LOB CLOSE :BFILE1 END-EXEC. EXEC SQL LOB CLOSE :DEST END-EXEC. END-OF-BLOB. EXEC SQL FREE :DEST END-EXEC. EXEC SQL FREE :BFILE1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
Dim OraDyn as OraDynaset, OraPhoto1 as OraBLOB, OraMyBfile as OraBFile OraConnection.BeginTrans Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id", ORADYN_DEFAULT) Set OraPhoto1 = OraDyn.Fields("ad_photo").Value OraDb.Parameters.Add "id", 3060,ORAPARAM_INPUT OraDb.Parameters.Add "mybfile", Null,ORAPARAM_OUTPUT OraDb.Parameters("mybfile").serverType = ORATYPE_BFILE OraDb.ExecuteSQL ("begin GetBFile(:id, :mybfile); end;") Set OraMyBFile = OraDb.Parameters("mybfile").Value 'Go to Next row OraDyn.MoveNext OraDyn.Edit 'Lets update OraPhoto1 data with that from the BFILE OraPhoto1.CopyFromBFile OraMyBFile OraDyn.Update OraConnection.CommitTrans
// Java IO classes: import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_45 { public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver ()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BFILE src_lob = null; BLOB dest_lob = null; InputStream in = null; OutputStream out = null; byte buf[] = new byte[1000]; ResultSet rset = null; rset = stmt.executeQuery ( "SELECT BFILENAME('ADPHOTO_DIR', 'keyboard_3106_13001') FROM DUAL"); if (rset.next()) { src_lob = ((OracleResultSet)rset).getBFILE (1); src_lob.openFile(); in = src_lob.getBinaryStream(); } rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 3106 AND AD_ID = 13001 FOR UPDATE"); if (rset.next()) { dest_lob = ((OracleResultSet)rset).getBLOB (1); // Fetch the output stream for dest_lob: out = dest_lob.getBinaryOutputStream(); } int length = 0; int pos = 0; while ((in != null) && (out != null) && ((length = in.read(buf)) != -1)) { System.out.println( "Pos = " + Integer.toString(pos) + ". Length = " + Integer.toString(length)); pos += length; out.write(buf, pos, length); } // Close all streams and file handles: in.close(); out.flush(); out.close(); src_lob.closeFile(); // Commit the transaction: conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to load an internal persistent BLOB with binary data from a BFILE.
Use LOADBLOBFROMFILE
for loading of binary data and LOADCLOBFROMFILE
for text loading. This achieves the same outcome as LOADFROMFILE
as well as returning the new offsets to the user. The LOADCLOBFROMFILE
API allows you to specify the character set id of the BFILE ensuring that the character set is properly converted from the BFILE data character set to the destination CLOB/NCLOB character set.
Since LOB
s can be quite large in size, it makes sense that SQL*Loader can load LOB
data from either the main datafile (that is, in-line with the rest of the data) or from one or more secondary datafiles.
To load LOB
data from the main datafile, the usual SQL*Loader formats can be used. LOB
data instances can be in predetermined size fields, delimited fields, or length-value pair fields.
For detailed information and tips on using SQL Loader for loading data into an internal LOB see "Loading Inline LOB Data" and "Loading Out-Of-Line LOB Data" in Chapter 4 of this guide.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The example procedures in this section use the Print_media
table of the Product Media sample schema and assume that there is an operating system source directory that contains the binary LOB
data to be loaded into the target BLOB
.
The example, "PL/SQL (DBMS_LOB Package): Loading an Internal Persistent BLOB with BFILE Data", illustrates LOADBLOBFROMFILE
usage in the PL/SQL programmatic environment. (Other programmatic environments are not supported.)
The following example illustrates:
LOADBLOBFROMFILE
to load the entire file without getting its length first.DECLARE src_loc BFILE := bfilename('ADVERT_DIR','display_ad_frame') ; dst_loc BLOB; src_offset NUMBER := 1; dst_offset NUMBER := 1; src_osin NUMBER; dst_osin NUMBER; bytes_rd NUMBER; bytes_wt NUMBER; BEGIN SELECT ad_composite INTO dst_loc FROM Print_media WHERE product_id=3106 and ad_id=13001 FOR UPDATE; /* Opening the source BFILE is mandatory */ dbms_lob.fileopen(src_loc, dbms_lob.file_readonly); /* Opening the LOB is optional */ dbms_lob.OPEN(dst_loc, dbms_lob.lob_readwrite); /* Save the input source/destination offsets */ src_osin := src_offset; dst_osin := dst_offset; /* Use LOBMAXSIZE to indicate loading the entire BFILE */ dbms_lob.LOADBLOBFROMFILE(dst_loc,src_loc,dbms_lob.lobmaxsize,src_offset,dst_ offset) ; /* Closing the LOB is mandatory if you have opened it */ dbms_lob.close(dst_loc); dbms_lob.filecloseall(); COMMIT; /* Use the src_offset returned to calculate the actual amount read from the BFILE */ bytes_rd := src_offset - src_osin; dbms_output.put_line(' Number of bytes read from the BFILE ' || bytes_rd ) ; /* Use the dst_offset returned to calculate the actual amount written to the BLOB */ bytes_wt := dst_offset - dst_osin; dbms_output.put_line(' Number of bytes written to the BLOB ' || bytes_wt ) ; /* If there is no exception the number of bytes read should equal to the number of bytes written */ END ;
This procedure describes how to load an internal persistent CLOB or NCLOB with character data from a BFILE.
Use LOADBLOBFROMFILE
for loading of binary data and LOADCLOBFROMFILE
for loading of text as the latter method lets you specify the character set id of the BFILE. The LOADCLOBFROMFILE
API allows you to specify the character set id of the BFILE ensuring that the character set is properly converted from the BFILE data character set to the destination CLOB/NCLOB character set.
Since LOB
s can be quite large in size, it makes sense that SQL*Loader can load LOB
data from either the main datafile (that is, in-line with the rest of the data) or from one or more secondary datafiles.
To load LOB
data from the main datafile, the usual SQL*Loader formats can be used. LOB
data instances can be in predetermined size fields, delimited fields, or length-value pair fields.
For detailed information and tips on using SQL Loader for loading data into an internal LOB see "Loading Inline LOB Data" and "Loading Out-Of-Line LOB Data" in Chapter 4 of this guide.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The example procedures in this section use the Print_media
table of the Product Media sample schema and assume that there is an operating system source directory that contains the character LOB data to be loaded into the target CLOB
or NCLOB
.
The examples given in, PL/SQL (DBMS_LOB Package): Loading an Internal Persistent CLOB with BFILE Data, illustrate LOADCLOBFROMFILE
usage in the PL/SQL programmatic environment. (Other programmatic environments are not supported.)
The following example illustrates:
0
).getlength
for the BFILE.This example assumes that ad_source
is a BFILE
in UTF8 character set format and the database character set is UTF8.
DECLARE src_loc bfile := bfilename('ADVERT_DIR','ad_source_1000') ; dst_loc clob ; amt number := dbms_lob.lobmaxsize; src_offset number := 1 ; dst_offset number := 1 ; lang_ctx number := dbms_lob.default_lang_ctx; warning number; BEGIN select ad_sourcetext into dst_loc from Print_media where product_id = 3000 and ad_id = 1000 for update ; dbms_lob.fileopen(src_loc, dbms_lob.file_readonly); /* The default_csid can be used when the BFILE encoding is in the same charset * as the destination CLOB/NCLOB charset */ dbms_lob.LOADCLOBFROMFILE(dst_loc,src_loc, amt, dst_offset, src_offset, dbms_lob.default_csid, lang_ctx,warning) ; commit; dbms_output.put_line(' Amount specified ' || amt ) ; dbms_output.put_line(' Number of bytes read from source: ' || (src_offset-1)); dbms_output.put_line(' Number of characters written to destination: ' || (dst_offset-1) ); if (warning = dbms_lob.warn_inconvertible_char) then dbms_output.put_line('Warning: Inconvertible character'); end if; dbms_lob.filecloseall() ; END ;
The following example illustrates:
NLS_CHARSET_ID
function.lang_ctx
.This example assumes that ad_file_ext_01
is a BFILE in JA16TSTSET format and the database national character set is AL16UTF16.
DECLARE src_loc bfile := bfilename('ADVERT_DIR','ad_file_ext_01') ; dst_loc1 nclob; dst_loc2 nclob; amt number := 1000; src_offset number := 1; dst_offset number := 1; src_osin number; cs_id number := NLS_CHARSET_ID('JA16TSTSET'); /* 998 */ lang_ctx number := dbms_lob.default_lang_ctx; warning number; BEGIN dbms_lob.fileopen(src_loc, dbms_lob.file_readonly); dbms_output.put_line(' BFILE csid is ' || cs_id) ; /* Load the first 1KB of the BFILE into dst_loc1 */ dbms_output.put_line(' ----------------------------' ) ; dbms_output.put_line(' First load ' ) ; dbms_output.put_line(' ----------------------------' ) ; SELECT ad_fltextn INTO dst_loc1 FROM Print_media WHERE product_id=3106 and ad_id=13000 FOR UPDATE; dbms_lob.LOADCLOBFROMFILE(dst_loc1, src_loc, amt, dst_offset, src_offset, cs_id, lang_ctx, warning); commit; /* the number bytes read may or may not be 1k */ dbms_output.put_line(' Amount specified ' || amt ) ; dbms_output.put_line(' Number of bytes read from source: ' || (src_offset-1)); dbms_output.put_line(' Number of characters written to destination: ' || (dst_offset-1) ); if (warning = dbms_lob.warn_inconvertible_char) then dbms_output.put_line('Warning: Inconvertible character'); end if; /* load the next 1KB of the BFILE into the dst_loc2 */ dbms_output.put_line(' ----------------------------' ) ; dbms_output.put_line(' Second load ' ) ; dbms_output.put_line(' ----------------------------' ) ; SELECT ad_fltextn INTO dst_loc2 FROM Print_media WHERE product_id=3106 and ad_id=13001 FOR UPDATE; /* Notice we are using the src_offset and lang_ctx returned from the previous * load. We do not use value 1001 as the src_offset here because sometimes the * actual amount read may not be the same as the amount specified. */ src_osin := src_offset; dst_offset := 1; dbms_lob.LOADCLOBFROMFILE(dst_loc2, src_loc, amt, dst_offset, src_offset, cs_id, lang_ctx, warning); commit ; dbms_output.put_line(' Number of bytes read from source: ' || (src_offset-src_osin) ); dbms_output.put_line(' Number of characters written to destination: ' || (dst_offset-1) ); if (warning = dbms_lob.warn_inconvertible_char) then dbms_output.put_line('Warning: Inconvertible character'); end if; dbms_lob.filecloseall() ; END ;
This procedure describes how to check if LOB is open.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The following "Checking if a LOB is Open" examples open a graphic image (ad_composite
), and then evaluate it to see if the LOB
is open.
Examples are provided in the following programmatic environments:
/* Checking if a LOB is Open. Note that the example procedure lobIsOpen_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE lobIsOpen_proc IS Lob_loc BLOB; Retval INTEGER; BEGIN SELECT ad_composite INTO Lob_loc FROM Print_media WHERE product_id = 3106 AND ad_id = 13001; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc , DBMS_LOB.LOB_READONLY); /* See if the LOB is open: */ Retval := DBMS_LOB.ISOPEN(Lob_loc); /* The value of Retval will be 1 meaning that the LOB is open. */ END;
/* Checking if LOB is Open. */ /* Select the locator into a locator variable */ sb4 select_adcomp_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_composite FROM Print_media WHERE product_id=2268 AND ad_id = 21001"; OCIDefine *defnp1 *defnp2; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) OCIDefineByPos(stmthp, &defnp2, errhp, (ub4) 2, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return (0); } void seeIfLOBIsOpen(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc; int isOpen; /* Allocate locator resources */ (void) OCIDescriptorAlloc((dvoid *)envhp, (dvoid **)&Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t)0, (dvoid **)0); /* Select the locator */ (void)select_adcomp_locator(Lob_loc, errhp, svchp, stmthp); /* See if the LOB is Open */ checkerr (errhp, OCILobIsOpen(svchp, errhp, Lob_loc, &isOpen)); if (isOpen) { printf(" Lob is Open\n"); /* ... Processing given that the LOB has already been Opened */ } else { printf(" Lob is not Open\n"); /* ... Processing given that the LOB has not been Opened */ } /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
* Checking if LOB is Open IDENTIFICATION DIVISION. PROGRAM-ID. LOB-OPEN. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 BLOB1 SQL-BLOB. 01 LOB-ATTR-GRP. 05 ISOPN PIC S9(9) COMP. 01 SRC SQL-BFILE. 01 DIR-ALIAS PIC X(30) VARYING. 01 FNAME PIC X(20) VARYING. 01 DIR-IND PIC S9(4) COMP. 01 FNAME-IND PIC S9(4) COMP. 01 USERID PIC X(11) VALUES "PM/PM". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. LOB-OPEN. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the target BLOB EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_COMPOSITE INTO :BLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 3060 AND AD_ID = 11001 END-EXEC. * See if the LOB is OPEN EXEC SQL LOB DESCRIBE :BLOB1 GET ISOPEN INTO :ISOPN END-EXEC. IF ISOPN = 1 * <Processing for the LOB OPEN case> DISPLAY "The LOB is open" ELSE * <Processing for the LOB NOT OPEN case> DISPLAY "The LOB is not open" END-IF. * Free the resources used by the BLOB END-OF-BLOB. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Checking if LOB is open */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void seeIfLOBIsOpen() { OCIBlobLocator *Lob_loc; int isOpen = 1; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_composite INTO :Lob_loc FROM Print_media WHERE product_id = 3106 and ad_id = 13001; /* See if the LOB is Open: */ EXEC SQL LOB DESCRIBE :Lob_loc GET ISOPEN INTO :isOpen; if (isOpen) printf("LOB is open\n"); else printf("LOB is not open\n"); /* Note that in this example, the LOB is not open */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "pm/pm"; EXEC SQL CONNECT :pm; seeIfLOBIsOpen(); EXEC SQL ROLLBACK WORK RELEASE; }
To see if a CLOB is open, your JDBC application can now use the isOpen
method defined in oracle.sql.CLOB
. The return boolean value indicates whether the CLOB has been previously opened or not. The isOpen
method is defined as follows:
/** * Check whether the CLOB is opened. * @return true if the LOB is opened. */ public boolean isOpen () throws SQLException
The usage example is:
CLOB clob = ... // See if the CLOB is opened boolean isOpen = clob.isOpen ();
To see if a BLOB is open, your JDBC application can now use the isOpen
method defined in oracle.sql.BLOB
. The return boolean value indicates whether the BLOB has been previously opened or not. The isOpen
method is defined as follows:
/** * Check whether the BLOB is opened. * @return true if the LOB is opened. */ public boolean isOpen () throws SQLException
The usage example is:
BLOB blob = ... // See if the BLOB is opened boolean isOpen = blob.isOpen ();
// Checking if LOB is open // Core JDBC classes: import java.io.OutputStream; import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.Types; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_48 { public Ex2_48 () { } public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB blob = null; ResultSet rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media product_id = 3060 AND ad_id = 11001"); if (rset.next()) { blob = ((OracleResultSet)rset).getBLOB (1); } OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall ( "BEGIN ? := DBMS_LOB.ISOPEN(?); END;"); cstmt.registerOutParameter (1, Types.NUMERIC); cstmt.setBLOB(2, blob); cstmt.execute(); int result = cstmt.getInt(1); System.out.println("The result is: " + Integer.toString(result)); OracleCallableStatement cstmt2 = (OracleCallableStatement) conn.prepareCall ( "BEGIN DBMS_LOB.OPEN(?,DBMS_LOB.LOB_READONLY); END;"); cstmt2.setBLOB(1, blob); cstmt2.execute(); System.out.println("The LOB has been opened with a call to DBMS_LOB.OPEN()"); // Use the existing cstmt handle to re-query the status of the locator: cstmt.setBLOB(2, blob); cstmt.execute(); result = cstmt.getInt(1); System.out.println("This result is: " + Integer.toString(result)); stmt.close(); cstmt.close(); cstmt2.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to migrate LONGs to LOBs using the (new) LONG-to-LOB API.
See Also:
Chapter 8, "Migrating From LONGs to LOBs" for further details on using the LONG-to-LOB API. |
Use the following syntax reference:
The fields used in the following example are:
CREATE TABLE Print_media ( product_id NUMBER NOT NULL, ad_id NUMBER NOT NULL, ad_sourcetext CLOB default EMPTY_CLOB(), ad_fltextn NCLOB default EMPTY_CLOB(), ad_graphic BFILE default NULL, ad_composite BLOB default EMPTY_BLOB(), ad_photo BLOB default EMPTY_BLOB(), ad_graphic BFILE default NULL, );
The following example assumes that the column, ad_sourcetext, of table PRINT_MEDIA
has been created as follows:
CREATE TABLE Print_media ( ... ad_sourcetext LONG, ... );
To convert the LONG column to CLOB just use ALTER TABLE
as follows:
ALTER TABLE Print_media MODIFY ( ad_sourcetext CLOB );
Any existing application using table Print_media
can continue to work with minor modification even after the column ad_sourcetext has been converted to type CLOB
. Chapter 8, "Migrating From LONGs to LOBs" provides examples of operations (binds and defines) used by LONGs and that continue to work for LOBs with minor modifications.
The following example illustrates how to use the LONG-to-LOB API with OCI:
/* Migrating from LONG to LOB Using LONG-to-LOB API */ word buflen, pid, aid; text buf2[5000]; text *insstmt = (text *) "INSERT INTO Print_media(product_id, ad_id, ad_sourcetext) VALUES (:PID, :AID, :ADSOURCE)"; if (OCIStmtPrepare(stmthp, errhp, insstmt, (ub4)strlen((char *)insstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)) { DISCARD printf("FAILED: OCIStmtPrepare()\n"); report_error(errhp); return; } if (OCIBindByName(stmthp, &bndhp[0], errhp, (text *) ":PID", (sb4) strlen((char *) ":PID"), (dvoid *) &buf1, (sb4) sizeof(buf1), SQLT_INT, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT) || OCIBindByName(stmthp, &bndhp[1], errhp, (text *) ":AID", (sb4) strlen((char *) ":AID"), (dvoid *) &buf1, (sb4) sizeof(buf1), SQLT_INT, (dvoid *) 0, (ub2 *) 0, (ub2 *) 1, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT) || OCIBindByName(stmthp, &bndhp[1], errhp, (text *) ":ADSOURCE", (sb4) strlen((char *) ":ADSOURCE"), (dvoid *) buf2, (sb4) sizeof(buf2), SQLT_CHR, (dvoid *) 0, (ub2 *) 0, (ub2 *) 3, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT)) { DISCARD printf("FAILED: OCIBindByName()\n"); report_error(errhp); return; } buf1 = 101; memset((void *)buf2, (int)'A', (size_t)5000); if (OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (const OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)) { DISCARD printf("FAILED: OCIStmtExecute()\n"); report_error(errhp); return; }
This procedure describes how to copy a LONG to a LOB using the TO_LOB operator.
Use of TO_LOB
is subject to the following limitations:
TO_LOB
to copy data to a LOB column, but not to a LOB attribute.TO_LOB
with any remote table. Consequently, all the following statements will fail:
INSERT INTO tb1@dblink (lob_col) SELECT TO_LOB(long_col) FROM tb2; INSERT INTO tb1 (lob_col) SELECT TO_LOB(long_col) FROM tb2@dblink; CREATE table tb1 AS SELECT TO_LOB(long_col) FROM tb2@dblink;
TO_LOB
operator cannot be used in the CREATE TABLE AS SELECT
statement to convert a LONG
or LONG
RAW
column to a LOB column when creating an Index Organized Table.
The workaround is to create the Index Organized Table, and then do an INSERT AS SELECT
of the LONG
or LONG
RAW
column using the TO_LOB
operator.
BEFORE
INSERT
or INSTEAD
OF
INSERT
-- the :NEW.lob_col
variable can't be referenced in the trigger body.TO_LOB
inside any PL/SQL block.Use the following syntax reference:
Assume that the following archival source table adlibrary_tab
was defined and contains data:
Rem This script is not needed if you use the (newer) Rem ALTER TABLE when migrating LONGs to LOBs CREATE TABLE adlibrary_tab ( product_id NUMBER(6), ad_id NUMBER(6), photos LONG RAW );
This example assumes that you want to copy the data from the LONG
RAW
column (photos
) into the BLOB
column (ad_photo
) of the Print_media
table, and uses the SQL function TO_LOB
to accomplish this.
The example is provided in SQL and applies to all programmatic environments:
INSERT INTO Print_media (product_id, ad_id, ad_photo) SELECT product_id, TO_LOB(photos) FROM adlibrary_tab WHERE product_id =3106;
Note: in order for the previous example to succeed, execute: CREATE TABLE adlibrary_tab ( product_id NUMBER, ad_audience LONG RAW); |
This functionality is based on using an operator on LONG
s called TO_LOB
that converts the LONG
to a LOB
. The TO_LOB
operator copies the data in all the rows of the LONG
column to the corresponding LOB
column, and then lets you apply the LOB
functionality to what was previously LONG
data. Note that the type of data that is stored in the LONG
column must match the type of data stored in the LOB
. For example, LONG
RAW
data must be copied to BLOB
data, and LONG
data must be copied to CLOB
data.
Once you have completed this one-time only operation and are satisfied that the data has been copied correctly, you could then drop the LONG
column. However, this will not reclaim all the storage originally required to store LONGs
in the table. In order to avoid unnecessary, excessive storage, you are better advised to copy the LONG
data to a LOB
in a new or different table. Once you have made sure that the data has been accurately copied, you should then drop the original table.
One simple way to effect this transposing of LONGs to LOBs is to use the CREATE
TABLE
... SELECT
statement, using the TO_LOB
operator on the LONG
column as part of the SELECT
statement. You can also use INSERT
... SELECT
.
In the examples in the following procedure, the LONG
column named long_col
in table Long_tab
is copied to a LOB
column named lob_col
in table Lob_tab
. These tables include an id
column that contains identification numbers for each row in the table.
Complete the following steps to copy data from a LONG
column to a LOB
column:
LONG
column, but use a LOB
datatype in place of the LONG
datatype.
For example, if you have a table with the following definition:
CREATE TABLE Long_tab ( id NUMBER, long_col LONG);
Create a new table using the following SQL statement:
CREATE TABLE Lob_tab ( id NUMBER, blob_col BLOB);
INSERT
command using the TO_LOB
operator to insert the data from the table with the LONG
datatype into the table with the LOB
datatype.
For example, issue the following SQL statement:
INSERT INTO Lob_tab SELECT id, TO_LOB(long_col) FROM long_tab;
LONG
column.
For example, issue the following SQL command to drop the LONG_TAB
table:
DROP TABLE Long_tab;
LONG
data. The synonym ensures that your database and applications continue to function properly.
For example, issue the following SQL statement:
CREATE SYNONYM Long_tab FOR Lob_tab;
Once the copy is complete, any applications that use the table must be modified to use the LOB
data.
You can use the TO_LOB
operator to copy the data from the LONG
to the LOB in statements that employ CREATE
TABLE
...AS
SELECT
or INSERT
...SELECT
. In the latter case, you must have already ALTER
ed the table and ADD
ed the LOB
column prior to the UPDATE
. If the UPDATE
returns an error (because of lack of undo space), you can incrementally migrate LONG
data to the LOB
using the WHERE
clause. The WHERE
clause cannot contain functions on the LOB
but can test the LOB
's nullness.
This procedure describes how to checkout a LOB.
The most efficient way to read large amounts of LOB data is to use OCILobRead
() with the streaming mechanism enabled using polling or callback. Use OCI , OCCI, or PRO*C interfaces with streaming for the underlying read operation. Using DBMS_LOB
.READ
will result in non-optimal performance.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
In the typical use of the checkout-checkin operation, the user wants to checkout a version of the LOB from the database to the client, modify the data on the client without accessing the database, and then checkin all the modifications that were made to the document on the client side. The checkin portion of the scenario is described in "Checking In a LOB".
The following examples are similar to examples provided in "Displaying LOB Data". Examples are provided in the following programmatic environments:
/* Checking out a LOB. The procedure checkOutLOB_proc used here is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE checkOutLOB_proc IS Lob_loc BLOB; Buffer VARCHAR2(32767); Amount BINARY_INTEGER := 32767; Position INTEGER := 2147483647; BEGIN /* Select the LOB: */ SELECT Nesttab.formatted_doc INTO Lob_loc FROM TABLE(SELECT PMtab.Textdoc_ntab FROM Print_media PMtab WHERE PMtab.product_id = 3106 AND PMtab.ad_id = 13001) Nesttab WHERE Nesttab.document_typ = 'PDF'; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); LOOP DBMS_LOB.READ (Lob_loc, Amount, Position, Buffer); /* Process the buffer: */ Position := Position + Amount; END LOOP; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('End of data'); END;
/* Checking out a lOB -- This example reads the entire contents of a BLOB piecewise into a buffer using a standard polling method, processing each buffer piece after every READ operation until the entire BLOB has been read: */ #define MAXBUFLEN 32767 /* Select the locator into a locator variable: */ sb4 select_formatteddoc_locator(Lob_loc, errhp, stmthp, svchp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *) "SELECT Intab.Transcript \ FROM TABLE(SELECT pm.ad_textdoc_ntab FROM Print_media pm \ WHERE pm.product_id = 3060 AND pm.ad_id = 11001) ntab \ WHERE ntab.document_typ = 'PDF'"; OCIDefine *defnp1, *defnp2; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_CLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) || OCIDefineByPos(stmthp, &defnp2, errhp, (ub4) 2, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_CLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row: */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } void checkoutLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc; ub4 amt; ub4 offset; sword retval; boolean done; ub1 bufp[MAXBUFLEN]; ub4 buflen; /* Allocate locators desriptors: */ (void) OCIDescriptorAlloc((dvoid *)envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB,(size_t) 0, (dvoid **) 0); /* Select the BLOB: */ printf(" select the formatted_doc locator...\n"); select_formatteddoc_locator(Lob_loc, errhp, stmthp, svchp); /* Open the CLOB: */ printf (" open lob in checkOutLOB_proc\n"); checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READONLY))); /* Setting amt = 0 will read till the end of LOB: */ amt = 0; buflen = sizeof(bufp); /* Process the data in pieces: */ printf (" read lob in pieces\n"); offset = 1; memset(bufp, '\0', MAXBUFLEN); done = FALSE; while (!done) { retval = OCILobRead(svchp, errhp, Lob_loc, &amt, offset, (dvoid *)bufp, buflen, (dvoid *)0,(sb4 (*)(dvoid *, dvoid *, ub4, ub1)) 0, (ub2) 0, (ub1) SQLCS_IMPLICIT); switch (retval) { case OCI_SUCCESS: /* Only one piece or last piece */ /* Process the data in bufp. amt will give the amount of data just read in bufp. This is in bytes for BLOBs and in characters for fixed width CLOBS and in bytes for variable width CLOBs */ done = TRUE; break; case OCI_ERROR: checkerr (errhp, OCI_ERROR); done = TRUE; break; case OCI_NEED_DATA: /* There are 2 or more pieces */ /* Process the data in bufp. amt will give the amount of data just read in bufp. This is in bytes for BLOBs and in characters for fixed width CLOBS and in bytes for variable width CLOBs. */ break; default: checkerr (errhp, retval); done = TRUE; break; } /* while */ } /* Closing the CLOB is mandatory if you have opened it: */ printf (" close lob in checkOutLOB_proc\n"); checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators: */ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
* Checking out a LOB IDENTIFICATION DIVISION. PROGRAM-ID. CHECKOUT. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "PM/PM". 01 CLOB1 SQL-CLOB. 01 BUFFER PIC X(5) VARYING. 01 AMT PIC S9(9) COMP. 01 OFFSET PIC S9(9) COMP VALUE 1. 01 D-BUFFER-LEN PIC 9. 01 D-AMT PIC 9. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. READ-CLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the CLOB locator: EXEC SQL ALLOCATE :CLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-CLOB END-EXEC. EXEC SQL SELECT AD_SOURCETEXT INTO :CLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 3060 AND AD_ID = 11001 END-EXEC. * Initiate polling read: MOVE 0 TO AMT. * Read first piece of the CLOB into the buffer: EXEC SQL LOB READ :AMT FROM :CLOB1 AT :OFFSET INTO :BUFFER END-EXEC. DISPLAY "Reading a CLOB ...". DISPLAY " ". MOVE BUFFER-LEN TO D-BUFFER-LEN. DISPLAY "first read (", D-BUFFER-LEN, "): " BUFFER-ARR(1:BUFFER-LEN). * Read subsequent pieces of the CLOB: READ-LOOP. MOVE " " TO BUFFER-ARR. EXEC SQL LOB READ :AMT FROM :CLOB1 INTO :BUFFER END-EXEC. MOVE BUFFER-LEN TO D-BUFFER-LEN. DISPLAY "next read (", D-BUFFER-LEN, "): " BUFFER-ARR(1:BUFFER-LEN). GO TO READ-LOOP. * Read the last piece of the CLOB: END-OF-CLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :CLOB1 END-EXEC. MOVE BUFFER-LEN TO D-BUFFER-LEN. DISPLAY "last read (", D-BUFFER-LEN, "): " BUFFER-ARR(1:BUFFER-LEN). EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Checking out a LOB - This example reads the entire contents of a CLOB piecewise into a buffer using a standard polling method, processing each buffer piece after every READ operation until the entire CLOB has been read: */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 256 void checkOutLOB_proc() { OCIClobLocator *Lob_loc; int Amount; int Clip_ID, Segment; VARCHAR Buffer[BufferLength]; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; /* Use Dynamic SQL to retrieve the LOB: */ EXEC SQL PREPARE S FROM 'SELECT Intab. \ FROM TABLE(SELECT PMtab.textdoc_ntab FROM Print_media PMtab \ WHERE PMtab.product_id = :pid AND PMtab.ad_id = :aid) ntab \ WHERE ntab.document_typ = :seg'; EXEC SQL DECLARE C CURSOR FOR S; Clip_ID = Segment = 1; EXEC SQL OPEN C USING :PID, :AID, :Segment; EXEC SQL FETCH C INTO :Lob_loc; EXEC SQL CLOSE C; /* Open the LOB: */ EXEC SQL LOB OPEN :Lob_loc READ ONLY; /* Setting Amount = 0 will initiate the polling method: */ Amount = 0; /* Set the maximum size of the Buffer: */ Buffer.len = BufferLength; EXEC SQL WHENEVER NOT FOUND DO break; while (TRUE) { /* Read a piece of the LOB into the Buffer: */ EXEC SQL LOB READ :Amount FROM :Lob_loc INTO :Buffer; printf("Checkout %d characters\n", Buffer.len); } printf("Checkout %d characters\n", Amount); /* Closing the LOB is mandatory if you have opened it: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *pm = "pm/pm"; EXEC SQL CONNECT :pm; checkOutLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Checking out a lOB 'There are two ways of reading a lob using orablob.read or orablob.copytofile 'Using OraBlob.Read mechanism Dim OraDyn as OraDynaset, OraPhoto as OraBlob, amount_read%, chunksize%, chunk chunksize = 32767 set OraDyn = OraDb.CreateDynaset("select * from Print_media", ORADYN_DEFAULT) set OraPhoto = OraDyn.Fields("ad_photo").Value OraPhoto.PollingAmount = OraPhoto.Size 'Read entire BLOB contents Do amount_read = OraPhoto.Read(chunk,chunksize) 'chunk returned is a variant of type byte array Loop Until OraPhoto.Status <> ORALOB_NEED_DATA 'Using OraBlob.CopyToFile mechanism Set OraDyn = OraDb.CreateDynaset("select * from Print_media", ORADYN_DEFAULT) Set OraPhoto = OraDyn.Fields("ad_photo").Value 'Read entire BLOB contents OraPhoto.CopyToFile "c:\myphoto.jpg"
// Checking out a LOB import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_59 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { CLOB src_lob = null; InputStream in = null; byte buf[] = new byte[MAXBUFSIZE]; ResultSet rset = stmt.executeQuery ( "SELECT ntab.formatted_doc FROM TABLE( " +" SELECT pm.ad_textdoc_ntab FROM Print_media pm " +" WHERE pm.product_id=3060 AND ad_id = 11001) ntab +" WHERE ntab.document_typ=`html'"); if (rset.next()) { src_lob = ((OracleResultSet)rset).getCLOB (1); in = src_lob.getAsciiStream(); } int length = 0; int pos = 0; while ((in != null) && ((length = in.read(buf)) != -1)) { pos += length; System.out.println(Integer.toString(pos)); // Process the buffer: } in.close(); rset.close(); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to check in a LOB.
The most efficient way to write large amounts of LOB data is to use OCILobWrite
() with the streaming mechanism enabled using polling or callback
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The checkin
operation demonstrated here follows from "Checking Out a LOB". In this case, the procedure writes the data back into the CLOB
formatted_doc
column within the nested table ad_textdoc_ntab
that contains interview segments. As noted earlier, you should use the OCI or PRO*C interface with streaming for the underlying write operation; using DBMS_LOB.WRITE
will result in non-optimal performance.
The following examples illustrate how to checkin a LOB using various programmatic environments:
Examples are provided in the following programmatic environments:
/* Checking in a LOB. The example procedure checkInLOB_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE checkInLOB_proc IS Lob_loc BLOB; Buffer VARCHAR2(32767); Amount BINARY_INTEGER := 32767; Position INTEGER := 2147483647; i INTEGER; BEGIN /* Select the LOB: */ SELECT ntab.formatted_doc INTO Lob_loc FROM TABLE(SELECT PMtab.Textdoc_ntab FROM Print_media PMtab WHERE PMtab.product_id = 3060 AND PMtab.ad_id = 11001) ntab WHERE ntab.document_typ = 'pdf' FOR UPDATE; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE) FOR i IN 1..3 LOOP /* Fill the Buffer with data to be written. */ /* Write data: */ DBMS_LOB.WRITE (Lob_loc, Amount, Position, Buffer); Position := Position + Amount; END LOOP; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Operation failed'); END;
/* Checking in a LOB. This example demonstrates how using OCI you can write arbitrary amounts of data to an Internal LOB in either a single piece of in multiple pieces using a streaming mechanism that utilizes standard polling. A statically allocated Buffer holds the data being written to the LOB. */ #define MAXBUFLEN 32767 /* Select the locator into a locator variable */ sb4 select_lock_formateddoc_locator(Lob_loc, errhp, stmthp,svchp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIDefine *defnp1, *defnp2; text *sqlstmt = (text *) "SELECT ntab.formatted_doc \ FROM TABLE(SELECT pm.ad_textdoc_ntab FROM Print_media pm \ WHERE pm.product_id = 2268 AND pm.ad_id = 21001) ntab \ WHERE ntab.document_typ = 'PDF' FOR UPDATE"; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_CLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) || OCIDefineByPos(stmthp, &defnp2, errhp, (ub4) 2, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_CLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) ); /* Execute and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return OCI_SUCCESS; } void checkinLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIClobLocator *Lob_loc; ub4 Total = 2.5*MAXBUFLEN; ub4 amtp; ub4 offset; ub4 remainder; ub4 nbytes; boolean last; ub1 bufp[MAXBUFLEN]; sb4 err; /* Allocate locators desriptors*/ (void) OCIDescriptorAlloc((dvoid *)envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB,(size_t) 0,(dvoid **) 0); /* Select the CLOB */ printf(" select the formatted_doc locator...\n"); select_lock_formatteddoc_locator(Lob_loc, errhp, stmthp, svchp); /* Open the CLOB */ printf (" open the locator.\n"); checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READWRITE))); printf (" write the lob in pieces\n"); if (Total > MAXBUFLEN) nbytes = MAXBUFLEN; /* We will use streaming via standard polling */ else nbytes = Total; /* Only a single write is required */ /* Fill the buffer with nbytes worth of data */ remainder = Total - nbytes; /* Setting Amount to 0 streams the data until use specifies OCI_LAST_PIECE */ amtp = 0; /* offset = <Starting position where to begin writing the data>; */ offset = 1; if (0 == remainder) { amtp = nbytes; /* Here, (Total <= MAXBUFLEN ) so we can write in one piece */ checkerr (errhp, OCILobWrite (svchp, errhp, Lob_loc, amtp, offset, bufp, nbytes, OCI_ONE_PIECE, (dvoid *) 0, (sb4 (*)(dvoid *,dvoid *,ub4 *,ub1 *)) 0, 0, SQLCS_IMPLICIT)); } else { /* Here (Total > MAXBUFLEN ) so we use streaming via standard polling */ /* write the first piece. Specifying first initiates polling. */ err = OCILobWrite (svchp, errhp, Lob_loc, &amtp, offset, bufp, nbytes, OCI_FIRST_PIECE, (dvoid *) 0, (sb4 (*)(dvoid *,dvoid *,ub4 *,ub1 *)) 0, 0, SQLCS_IMPLICIT); if (err != OCI_NEED_DATA) checkerr (errhp, err); last = FALSE; /* write the next (interim) and last pieces */ do { if (remainder > MAXBUFLEN) nbytes = MAXBUFLEN; /* Still have more pieces to go */ else { nbytes = remainder; /* Here, (remainder <= MAXBUFLEN) */ last = TRUE; /* This is going to be the Final piece */ } /* Fill the buffer with nbytes worth of data */ if (last) { /* Specifying LAST terminates polling */ err = OCILobWrite (svchp, errhp, Lob_loc, &amtp, offset, bufp, nbytes, OCI_LAST_PIECE, (dvoid *) 0, (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, 0, SQLCS_IMPLICIT); if (err != OCI_SUCCESS) checkerr(errhp, err); } else { err = OCILobWrite (svchp, errhp, Lob_loc, &amtp, offset, bufp, nbytes, OCI_NEXT_PIECE, (dvoid *) 0, (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, 0, SQLCS_IMPLICIT); if (err != OCI_NEED_DATA) checkerr (errhp, err); } /* Determine how much is left to write */ remainder = remainder - nbytes; } while (!last); } /* At this point, (remainder == 0) */ /* Closing the BLOB is mandatory if you have opened it */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); }
* Checking in a LOB IDENTIFICATION DIVISION. PROGRAM-ID. CHECKIN. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INFILE ASSIGN TO "datfile.dat" ORGANIZATION IS SEQUENTIAL. DATA DIVISION. FILE SECTION. FD INFILE RECORD CONTAINS 80 CHARACTERS. 01 INREC PIC X(80). WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "P/PM". 01 CLOB1 SQL-CLOB.M 01 BUFFER PIC X(80) VARYING. 01 AMT PIC S9(9) COMP VALUE 0. 01 OFFSET PIC S9(9) COMP VALUE 1. 01 END-OF-FILE PIC X(1) VALUES "N". 01 D-BUFFER-LEN PIC 9. 01 D-AMT PIC 9. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. WRITE-CLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the CLOB locator: EXEC SQL ALLOCATE :CLOB1 END-EXEC. EXEC SQL SELECT AD_SOURCETEXT INTO :CLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 3060 AND AD_ID = 11001 FOR UPDATE END-EXEC. * Open the input file for reading: OPEN INPUT INFILE. * Either write entire record or write first piece. * Read a data file here and populate BUFFER-ARR and BUFFER-LEN. * END-OF-FILE will be set to "Y" when the entire file has been * read. PERFORM READ-NEXT-RECORD. MOVE INREC TO BUFFER-ARR. MOVE 80 TO BUFFER-LEN. IF (END-OF-FILE = "Y") MOVE 80 TO AMT EXEC SQL LOB WRITE ONE :AMT FROM :BUFFER INTO :CLOB1 AT :OFFSET END-EXEC ELSE DISPLAY "LOB WRITE FIRST" DISPLAY BUFFER-ARR MOVE 321 TO AMT EXEC SQL LOB WRITE FIRST :AMT FROM :BUFFER INTO :CLOB1 END-EXEC END-IF. * Continue reading from the input data file * and writing to the CLOB: PERFORM READ-WRITE UNTIL END-OF-FILE = "Y". PERFORM SIGN-OFF. STOP RUN. READ-WRITE. PERFORM READ-NEXT-RECORD. MOVE INREC TO BUFFER-ARR. DISPLAY "READ-WRITE". DISPLAY INREC. MOVE 80 TO BUFFER-LEN. IF END-OF-FILE = "Y" DISPLAY "LOB WRITE LAST: ", BUFFER-ARR MOVE 1 TO BUFFER-LEN EXEC SQL LOB WRITE LAST :AMT FROM :BUFFER INTO :CLOB1 END-EXEC ELSE DISPLAY "LOB WRITE NEXT: ", BUFFER-ARR MOVE 0 TO AMT EXEC SQL LOB WRITE NEXT :AMT FROM :BUFFER INTO :CLOB1 END-EXEC END-IF. READ-NEXT-RECORD. MOVE SPACES TO INREC. READ INFILE NEXT RECORD AT END MOVE "Y" TO END-OF-FILE. SIGN-OFF. CLOSE INFILE. EXEC SQL FREE :CLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Checking in a LOB. This example shows how you can use Pro*C/C++ to WRITE arbitrary amounts of data to an Internal LOB in either a single piece or in multiple pieces using a Streaming Mechanism that utilizes standard polling. A static Buffer holds the data being written: */ #include <oci.h> #include <stdio.h> #include <string.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 512 void checkInLOB_proc(multiple) int multiple; { OCIClobLocator *Lob_loc; VARCHAR Buffer[BufferLength]; unsigned int Total; unsigned int Amount; unsigned int remainder, nbytes; boolean last; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate and Initialize the Locator: */ EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_sourcetext INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Open the LOB: */ EXEC SQL LOB OPEN :Lob_loc READ WRITE; Total = Amount = (multiple * BufferLength); if (Total > BufferLength) nbytes = BufferLength; /* We will use streaming via standard polling */ else nbytes = Total; /* Only a single WRITE is required */ /* Fill the Buffer with nbytes worth of data: */ memset((void *)Buffer.arr, 32, nbytes); Buffer.len = nbytes; /* Set the Length */ remainder = Total - nbytes; if (0 == remainder) { /* Here, (Total <= BufferLength) so we can WRITE in ONE piece: */ EXEC SQL LOB WRITE ONE :Amount FROM :Buffer INTO :Lob_loc; printf("Write ONE Total of %d characters\n", Amount); } else { /* Here (Total > BufferLength) so use streaming via standard polling: WRITE the FIRST piece. Specifying FIRST initiates polling: */ EXEC SQL LOB WRITE FIRST :Amount FROM :Buffer INTO :Lob_loc; printf("Write FIRST %d characters\n", Buffer.len); last = FALSE; /* WRITE the NEXT (interim) and LAST pieces: */ do { if (remainder > BufferLength) nbytes = BufferLength; /* Still have more pieces to go */ else { nbytes = remainder; last = TRUE; /* This is going to be the Final piece */ } /* Fill the Buffer with nbytes worth of data: */ memset((void *)Buffer.arr, 32, nbytes); Buffer.len = nbytes; /* Set the Length */ if (last) { EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Specifying LAST terminates polling: */ EXEC SQL LOB WRITE LAST :Amount FROM :Buffer INTO :Lob_loc; printf("Write LAST Total of %d characters\n", Amount); } else { EXEC SQL WHENEVER SQLERROR DO break; EXEC SQL LOB WRITE NEXT :Amount FROM :Buffer INTO :Lob_loc; printf("Write NEXT %d characters\n", Buffer.len); } /* Determine how much is left to WRITE: */ remainder = remainder - nbytes; } while (!last); } EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* At this point, (Amount == Total), the total amount that was written */ /* Close the LOB: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; checkInLOB_proc(1); EXEC SQL ROLLBACK WORK; checkInLOB_proc(4); EXEC SQL ROLLBACK WORK RELEASE; }
'Checking in a LOB 'There are two ways of writing a lob - using orablob.write or orablob.copyfromfile 'Using the OraBlob.Write mechanism Dim MySession As OraSession Dim OraDb As OraDatabase Dim fnum As Integer Dim OraDyn As OraDynaset, OraPhoto As OraBlob, amount_written%, chunksize%, curchunk() As Byte Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "pm/pm", 0&) chunksize = 500 ReDim curchunk(chunksize) Set OraDyn = OraDb.CreateDynaset("SELECT * FROM Print_media", ORADYN_DEFAULT) Set OraPhoto = OraDyn.Fields("ad_photo").Value fnum = FreeFile Open "c:\tmp\keyboard_3016_13001.jpg" For Binary As #fnum OraPhoto.offset = 1 OraPhoto.pollingAmount = LOF(fnum) remainder = LOF(fnum) Dim piece As Byte Get #fnum, , curchunk OraDyn.Edit piece = ORALOB_FIRST_PIECE OraPhoto.Write curchunk, chunksize, ORALOB_FIRST_PIECE While OraPhoto.Status = ORALOB_NEED_DATA remainder = remainder - chunksize If remainder <= chunksize Then chunksize = remainder piece = ORALOB_LAST_PIECE Else piece = ORALOB_NEXT_PIECE End If Get #fnum, , curchunk OraPhoto.Write curchunk, chunksize, piece Wend OraDyn.Update 'Using the OraBlob.CopyFromFile mechanism Set OraDyn = OraDb.CreateDynaset("select * from Print_media order by product_ id, ad_id", ORADYN_DEFAULT) Set OraPhoto = OraDyn.Fields("ad_photo").Value OraDyn.Edit OraPhoto.CopyFromFile "c:\tmp\keyboard3016_13001.jpg" OraDyn.Update
// Checking in a LOB import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_66 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { CLOB lob_loc = null; String buf = new String ("Some Text To Write for the Ad"); ResultSet rset = stmt.executeQuery ( "SELECT ad_sourcetext FROM Print_media WHERE product_id = 2268 AND ad_id = 21001 FOR UPDATE"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getCLOB (1); } long pos = 0; // Offset within the CLOB where the data is to be written long length = 0; // This is the size of the buffer to be written // This loop writes the buffer three times consecutively: for (int i = 0; i < 3; i++) { pos = lob_loc.length(); // an alternative is: lob_loc.putString(pos, buf); lob_loc.putString(pos, buf); // Some debug information: System.out.println(" putString(" + Long.toString(pos) +" buf);"); } stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to display LOB data.
The most efficient way to read large amounts of LOB data is to use OCILobRead
() with the streaming mechanism enabled.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
As an example of displaying a LOB, our scenario stream-reads the image logo
from the column object ad_header
onto the client-side in order to view the data.
Examples are provided in the following programmatic environments:
/* Displaying LOB data.The example procedure displayLOB_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE displayLOB_proc IS Lob_loc BLOB; Buffer RAW(1024); Amount BINARY_INTEGER := 1024; Position INTEGER := 1; BEGIN /* Select the LOB: */ SELECT pm.ad_header.logo INTO Lob_loc FROM print_media pm WHERE pm.product_id = 3060 AND pm.ad_id = 11001; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); LOOP DBMS_LOB.READ (Lob_loc, Amount, Position, Buffer); /* Display the buffer contents: */ DBMS_OUTPUT.PUT_LINE(utl_raw.cast_to_varchar2(Buffer)); Position := Position + Amount; END LOOP; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('End of data'); END;
/* Displaying LOB data. This example reads the entire contents of a BLOB piecewise into a buffer using the standard polling method, processing each buffer piece after every READ operation until the entire BLOB has been read. */ #define MAXBUFLEN 32767 /* Select the locator into a locator variable */ sb4 select_mapobjectdrawing_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIDefine *defnp1, *defnp2; text *sqlstmt = (text *) "SELECT pm.Adheader_type.logo \ FROM Print_media pm WHERE pm.product_id = 3060 AND ad_id = 11001"; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) || OCIDefineByPos(stmthp, &defnp2, errhp, (ub4) 2, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) ); /* Execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } void displayLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIBlobLocator *Lob_loc; ub4 amt; ub4 offset; sword retval; boolean done; ub1 bufp[MAXBUFLEN]; ub4 buflen; OCILobLocator *Lob_Loc; /* Allocate the Source (bfile) & destination (blob) locators desriptors*/ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the BLOB */ printf(" select the adheaderlogo locator...\n"); select_adheaderlogo_locator(Lob_loc, errhp, svchp, stmthp); /* Open the BLOB */ printf(" open the lob\n"); checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READONLY))); /* Setting amt = 0 will read till the end of LOB*/ amt = 0; buflen = sizeof(bufp); /* Process the data in pieces */ printf(" Process the data in pieces\n"); offset = 1; memset(bufp, '\0', MAXBUFLEN); done = FALSE; while (!done) { retval = OCILobRead(svchp, errhp, Lob_loc, &amt, offset, (dvoid *) bufp, buflen, (dvoid *)0, (sb4 (*)(dvoid *, dvoid *, ub4, ub1)) 0, (ub2) 0, (ub1) SQLCS_IMPLICIT); switch (retval) { case OCI_SUCCESS: /* Only one piece or last piece*/ /* Process the data in bufp. amt will give the amount of data just read in bufp. This is in bytes for BLOBs and in characters for fixed width CLOBS and in bytes for variable width CLOBs */ done = TRUE; break; case OCI_ERROR: checkerr (errhp, retval); done = TRUE; break; case OCI_NEED_DATA: /* There are 2 or more pieces */ /* Process the data in bufp. amt will give the amount of data just read in bufp. This is in bytes for BLOBs and in characters for fixed width CLOBS and in bytes for variable width CLOBs */ break; default: checkerr (errhp, retval); done = TRUE; break; } } /* while */ /* Closing the BLOB is mandatory if you have opened it */ printf(" close the lob \n"); checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); }
* DISPLAYING LOB DATA IDENTIFICATION DIVISION. PROGRAM-ID. DISPLAY-BLOB. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 BLOB1 SQL-BLOB. 01 BUFFER2 PIC X(5) VARYING. 01 AMT PIC S9(9) COMP. 01 OFFSET PIC S9(9) COMP VALUE 1. 01 D-AMT PIC 9. EXEC SQL VAR BUFFER2 IS RAW(5) END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. DISPLAY-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locator: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT PM.AD_PHOTO INTO :BLOB1 FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 2268 AND AD_ID = 21001 END-EXEC. DISPLAY "Found column AD_PHOTO". * Initiate polling read: MOVE 0 TO AMT. EXEC SQL LOB READ :AMT FROM :BLOB1 AT :OFFSET INTO :BUFFER2 END-EXEC. DISPLAY " ". MOVE AMT TO D-AMT. DISPLAY "first read (", D-AMT, "): " BUFFER2. READ-BLOB-LOOP. MOVE " " TO BUFFER2. EXEC SQL LOB READ :AMT FROM :BLOB1 INTO :BUFFER2 END-EXEC. MOVE AMT TO D-AMT. DISPLAY "next read (", D-AMT, "): " BUFFER2. GO TO READ-BLOB-LOOP. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. MOVE AMT TO D-AMT. DISPLAY "last read (", D-AMT, "): " BUFFER2(1:AMT). EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Displaying LOB data. This example reads the entire contents of a BLOB piecewise into a buffer using a standard polling method, processing each buffer piece after every READ operation until the entire BLOB has been read: */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 32767 void displayLOB_proc() { OCIBlobLocator *Lob_loc; int Amount; struct { unsigned short Length; char Data[BufferLength]; } Buffer; /* Datatype equivalencing is mandatory for this datatype: */ EXEC SQL VAR Buffer IS VARRAW(BufferLength); EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; /* Select the BLOB: */ EXEC SQL SELECT m.ad_header.header_text INTO Lob_loc FROM Print_media m WHERE m.product_id = 3060 AND ad_id = 11001; /* Open the BLOB: */ EXEC SQL LOB OPEN :Lob_loc READ ONLY; /* Setting Amount = 0 will initiate the polling method: */ Amount = 0; /* Set the maximum size of the Buffer: */ Buffer.Length = BufferLength; EXEC SQL WHENEVER NOT FOUND DO break; while (TRUE) { /* Read a piece of the BLOB into the Buffer: */ EXEC SQL LOB READ :Amount FROM :Lob_loc INTO :Buffer; /* Process (Buffer.Length == BufferLength) amount of Buffer.Data */ } /* Process (Buffer.Length == Amount) amount of Buffer.Data */ /* Closing the BLOB is mandatory if you have opened it: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; displayLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Displaying LOB data 'Using the OraClob.Read mechanism Dim MySession As OraSession Dim OraDb As OraDatabase Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Dim OraDyn as OraDynaset, OraAdSourceText as OraClob, amount_read%, chunksize%, chunk chunksize = 32767 Set OraDyn = OraDb.CreateDynaset("SELECT * FROM Print_media", ORADYN_DEFAULT) Set OraAdSourceText = OraDyn.Fields("ad_sourcetext").Value OraAdSourceText.PollingAmount = OraAdSourceText.Size 'Read entire CLOB contents Do 'chunk returned is a variant of type byte array: amount_read = OraAdSourceText.Read(chunk, chunksize) 'Msgbox chnunk Loop Until OraAdSourceText.Status <> ORALOB_NEED_DATA
// Core JDBC classes: import java.io.OutputStream; import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_72 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB lob_loc = null; InputStream in = null; byte buf[] = new byte[MAXBUFSIZE]; int pos = 0; int length = 0; ResultSet rset = stmt.executeQuery ( "SELECT pm.ad_header.logo FROM Print_media pm WHERE pm.product_id = 2056 AND ad_id = 12001"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getBLOB (1); } // read this LOB through an InputStream: in = lob_loc.getBinaryStream(); while ((length = in.read(buf)) != -1) { pos += length; System.out.println(Integer.toString(pos)); // Process the contents of the buffer here. } in.close(); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to read data from LOBs.
The most efficient way to read large amounts of LOB data is to use OCILobRead
() with the streaming mechanism enabled using polling or callback.
When reading the LOB
value, it is not an error to try to read beyond the end of the LOB
. This means that you can always specify an input amount of 4 gigabytes - 1 regardless of the starting offset and the amount of data in the LOB. Hence, you do not need to incur a round-trip to the server to call OCILobGetLength
() to find out the length of the LOB value to determine the amount to read.
Assume that the length of a LOB is 5,000 bytes and you want to read the entire LOB value starting at offset 1,000. Also assume that you do not know the current length of the LOB value. Here's the OCI read call, excluding the initialization of all parameters:
#define MAX_LOB_SIZE 4294967295 ub4 amount = MAX_LOB_SIZE; ub4 offset = 1000; OCILobRead(svchp, errhp, locp, &amount, offset, bufp, bufl, 0, 0, 0, 0)
amount
' parameter after each OCILobRead
() call to see how many bytes were read into the buffer since the buffer may not be entirely full.len
' parameter, which is input to the callback, will indicate how many bytes are filled in the buffer. Be sure to check the 'len
' parameter during your callback processing since the entire buffer may not be filled with data (see the Oracle Call Interface Programmer's Guide.)A chunk is one or more Oracle blocks. You can specify the chunk size for the LOB
when creating the table that contains the LOB
. This corresponds to the chunk size used by Oracle when accessing or modifying the LOB
value. Part of the chunk is used to store system-related information and the rest stores the LOB
value. The getchunksize
function returns the amount of space used in the LOB
chunk to store the LOB
value.
You will improve performance if you execute read
requests using a multiple of this chunk size. The reason for this is that you are using the same unit that the Oracle database uses when reading data from disk. If it is appropriate for your application, you should batch reads until you have enough for an entire chunk instead of issuing several LOB
read calls that operate on the same LOB
chunk.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The examples read data from a single image.
Examples are provided in the following programmatic environments:
/* Reading LOB data. The example procedure readLOB_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE readLOB_proc IS Lob_loc BLOB; Buffer RAW(32767); Amount BINARY_INTEGER := 32767; Position INTEGER := 1000; Chunksize INTEGER; BEGIN /* Select the LOB: */ SELECT ad_composite INTO Lob_loc FROM print_media WHERE product_id = 3060 AND ad_id = 11001; /* Find out the chunksize for this LOB column: */ Chunksize := DBMS_LOB.GETCHUNKSIZE(Lob_loc); IF (Chunksize < 32767) THEN Amount := (32767 / Chunksize) * Chunksize; END IF; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); /* Read data from the LOB: */ DBMS_LOB.READ (Lob_loc, Amount, Position, Buffer); /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); END;
/* Reading LOB data. This example reads the entire contents of a BLOB piecewise into a buffer using a standard polling method, processing each buffer piece after every READ operation until the entire BLOB has been read. */ #define MAXBUFLEN 1000 /* Select the locator into a locator variable */ sb4 select_frame_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIDefine *defnp1; text *sqlstmt = (text *) "SELECT ad_composite \ FROM Print_media pm \ WHERE pm.product_id = 2268"; printf(" prepare statement in select_adcomposite_locator\n"); checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); printf(" OCIDefineByPos in select_adcomposite_locator\n"); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row */ printf(" OCIStmtExecute in select_adcomposite_locator\n"); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } void readLOB_proc(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { ub4 amt; ub4 offset; sword retval; ub1 bufp[MAXBUFLEN]; ub4 buflen; boolean done; OCILobLocator *Lob_loc; OCILobLocator *blob; /* Allocate the Source (bfile) & destination (blob) locators descriptors*/ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the BLOB */ printf(" call select_ad4read_locator\n"); select_adcomposite_locator(Lob_loc, errhp, svchp, stmthp); /* Open the BLOB */ printf(" call OCILobOpen\n"); checkerr (errhp, OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READONLY)); /* Setting the amt to the buffer length. Note here that amt is in bytes since we are using a BLOB */ amt = 0; buflen = sizeof(bufp); /* Process the data in pieces */ printf(" process the data in pieces\n"); offset = 1; memset(bufp, '\0', MAXBUFLEN); done = FALSE; while (!done) { retval = OCILobRead(svchp, errhp, Lob_loc, &amt, offset, (dvoid *) bufp, buflen, (dvoid *)0, (sb4 (*)(dvoid *, dvoid *, ub4, ub1)) 0, (ub2) 0, (ub1) SQLCS_IMPLICIT); switch (retval) { case OCI_SUCCESS: /* Only one piece since amtp == bufp */ /* Process the data in bufp. amt will give the amount of data just read in bufp. This is in bytes for BLOBs and in characters for fixed width CLOBS and in bytes for variable width CLOBs */ printf("[%.*s]\n", buflen, bufp); done = TRUE; break; case OCI_ERROR: /* report_error(); this function is not shown here */ done = TRUE; break; case OCI_NEED_DATA: printf("[%.*s]\n", buflen, bufp); break; default: (void) printf("Unexpected ERROR: OCILobRead() LOB.\n"); done = TRUE; break; } } /* Closing the BLOB is mandatory if you have opened it */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); }
* READING LOB DATA IDENTIFICATION DIVISION. PROGRAM-ID. ONE-READ-BLOB. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 BLOB1 SQL-BLOB. 01 BUFFER2 PIC X(32767) VARYING. 01 AMT PIC S9(9) COMP. 01 OFFSET PIC S9(9) COMP VALUE 1. 01 USERID PIC X(11) VALUES "PM/PM". EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL VAR BUFFER2 IS LONG RAW(32767) END-EXEC. PROCEDURE DIVISION. ONE-READ-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the CLOB locator: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_COMPOSITE INTO :BLOB1 FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 2268 AND AD_ID = 21001 END-EXEC. EXEC SQL LOB OPEN :BLOB1 END-EXEC. * Perform a single read: MOVE 32767 TO AMT. EXEC SQL LOB READ :AMT FROM :BLOB1 INTO :BUFFER2 END-EXEC. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. END-OF-BLOB. DISPLAY "BUFFER2: ", BUFFER2(1:AMT). EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Reading LOB data #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 32767 void readLOB_proc() { OCIBlobLocator *Lob_loc; int Amount = BufferLength; /* Here (Amount == BufferLength) so only one READ is needed: */ char Buffer[BufferLength]; /* Datatype equivalencing is mandatory for this datatype: */ EXEC SQL VAR Buffer IS RAW(BufferLength); EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_composite INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; /* Open the BLOB: */ EXEC SQL LOB OPEN :Lob_loc READ ONLY; EXEC SQL WHENEVER NOT FOUND CONTINUE; /* Read the BLOB data into the Buffer: */ EXEC SQL LOB READ :Amount FROM :Lob_loc INTO :Buffer; printf("Read %d bytes\n", Amount); /* Close the BLOB: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "pm/pm"; EXEC SQL CONNECT :pm; readLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Reading LOB data using the OraClob.Read mechanism Dim MySession As OraSession Dim OraDb As OraDatabase Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Dim OraDyn as OraDynaset, OraAdSourceText as OraClob, amount_read%, chunksize%, chunk chunksize = 32767 Set OraDyn = OraDb.CreateDynaset("SELECT * FROM Print_media", ORADYN_DEFAULT) Set OraAdSourceText = OraDyn.Fields("ad_sourcetext").Value OraAdSourceText.pollingAmount = OraAdSourceText.Size 'Read entire CLOB contents Do amount_read = OraAdSourceText.Read(chunk,chunksize) 'chunk returned is a variant of type byte array Loop Until OraAdSourceText.Status <> ORALOB_NEED_DATA
// Reading LOB data // Java IO classes: import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_79 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB lob_loc = null; byte buf[] = new byte[MAXBUFSIZE]; ResultSet rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media WHERE product_id = 2056 AND ad_ id = 12001"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getBLOB (1); } // MAXBUFSIZE is the number of bytes to read and 1000 is the offset from // which to start reading buf = lob_loc.getBytes(1000, MAXBUFSIZE); // Display the contents of the buffer here: System.out.println(new String(buf)); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to read portion of the LOB (substring).
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
This example demonstrates reading a portion from image ad_photo
.
Examples are provided in the following programmatic environments:
/* Reading portion of the LOB data using substr. Example procedure substringLOB_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE substringLOB_proc IS Lob_loc BLOB; Amount BINARY_INTEGER := 32767; Position INTEGER := 1024; Buffer RAW(32767); BEGIN /* Select the LOB: */ SELECT ad_photo INTO Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); Buffer := DBMS_LOB.SUBSTR(Lob_loc, Amount, Position); /* Process the data */ /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); END; /* In the following SQL statement, 255 is the amount to read and 1 is the starting offset from which to read: */ SELECT DBMS_LOB.SUBSTR(ad_photo, 255, 1) FROM Print_media WHERE product_id = 3060 AND ad_id = 11001;
* READING PORTION OF THE LOB DATA USING SUBSTR IDENTIFICATION DIVISION. PROGRAM-ID. BLOB-SUBSTR. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 BLOB1 SQL-BLOB. 01 BUFFER2 PIC X(32767) VARYING. 01 AMT PIC S9(9) COMP. 01 POS PIC S9(9) COMP VALUE 1. 01 USERID PIC X(11) VALUES "SAMP/SAMP". EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL VAR BUFFER2 IS VARRAW(32767) END-EXEC. PROCEDURE DIVISION. BLOB-SUBSTR. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the CLOB locator: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_COMPOSITE INTO :BLOB1 FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 2268 AND AD_ID = 21001 END-EXEC. DISPLAY "Selected the BLOB". * Open the BLOB for READ ONLY: EXEC SQL LOB OPEN :BLOB1 READ ONLY END-EXEC. * Execute PL/SQL to get SUBSTR functionality: MOVE 5 TO AMT. EXEC SQL EXECUTE BEGIN :BUFFER2 := DBMS_LOB.SUBSTR(:BLOB1,:AMT,:POS); END; END-EXEC. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. DISPLAY "Substr: ", BUFFER2-ARR(POS:AMT). END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Reading portion of the LOB using (substr). Pro*C/C++ lacks an equivalent embedded SQL form for the DBMS_LOB.SUBSTR() function. However, Pro*C/C++ can interoperate with PL/SQL using anonymous PL/SQL blocks embedded in a Pro*C/C++ program as this example shows: */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 32767 void substringLOB_proc() { OCIBlobLocator *Lob_loc; int Position = 1; int Amount = BufferLength; struct { unsigned short Length; char Data[BufferLength]; } Buffer; /* Datatype equivalencing is mandatory for this datatype: */ EXEC SQL VAR Buffer IS VARRAW(BufferLength); EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_photo INTO Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; /* Open the BLOB: */ EXEC SQL LOB OPEN :Lob_loc READ ONLY; /* Invoke SUBSTR() from within an anonymous PL/SQL block: */ EXEC SQL EXECUTE BEGIN :Buffer := DBMS_LOB.SUBSTR(:Lob_loc, :Amount, :Position); END; END-EXEC; /* Close the BLOB: */ EXEC SQL LOB CLOSE :Lob_loc; /* Process the Data */ /* Release resources used by the locator: */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; substringLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; exit(0); }
'Reading portion of a LOB (or BFILE). In OO4O this is accomplished by 'setting the OraBlob.Offset and OraBlob.chunksize properties. 'Using the OraClob.Read mechanism Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn as OraDynaset, OraAdSourceText as OraClob, amount_read%, chunksize%, chunk Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset("SELECT * FROM Print_media", ORADYN_DEFAULT) Set OraAdSourceText = OraDyn.Fields("ad_sourcetext").Value 'Let's read 100 bytes from the 500th byte onwards: OraAdSourceText.Offset = 500 OraAdSourceText.PollingAmount = OraAdSourceText.Size 'Read entire CLOB contents amount_read = OraAdSourceText.Read(chunk, 100) 'chunk returned is a variant of type byte array
// Reading portion of a LOB using substr import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_79 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB lob_loc = null; byte buf[] = new byte[MAXBUFSIZE]; ResultSet rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media WHERE product_id = 3106 AND ad_id = 13001"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getBLOB (1); } OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall ("BEGIN DBMS_LOB.OPEN(?, " +"DBMS_LOB.LOB_READONLY); END;"); cstmt.setBLOB(1, lob_loc); cstmt.execute(); // MAXBUFSIZE is the number of bytes to read and 1000 is the offset from // which to start reading: buf = lob_loc.getBytes(1000, MAXBUFSIZE); // Display the contents of the buffer here. cstmt = (OracleCallableStatement) conn.prepareCall ("BEGIN DBMS_LOB.CLOSE(?); END;"); cstmt.setBLOB(1, lob_loc); cstmt.execute(); stmt.close(); cstmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to compare all or part of two LOBs.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The following examples compare two images from the table Print_media
to see whether they are different.
Examples are provided in the following programmatic environments:
/* Comparing all or part of two LOBs. The example procedure compareTwoLOBs_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE compareTwoLOBs_proc IS Lob_loc1 BLOB; Lob_loc2 BLOB; Amount INTEGER := 32767; Retval INTEGER; BEGIN /* Select the LOB: */ SELECT ad_composite INTO Lob_loc1 FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; SELECT ad_composite INTO Lob_loc2 FROM Print_media WHERE product_id = 2056 AND ad_id = 12001; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc1, DBMS_LOB.LOB_READONLY); DBMS_LOB.OPEN (Lob_loc2, DBMS_LOB.LOB_READONLY); /* Compare the two frames: */ retval := DBMS_LOB.COMPARE(Lob_loc1, Lob_loc2, Amount, 1, 1); IF retval = 0 THEN DBMS_OUTPUT.PUT_LINE('Processing for equal frames'); ELSE DBMS_OUTPUT.PUT_LINE('Processing for non-equal frames'); END IF; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc1); DBMS_LOB.CLOSE (Lob_loc2); END;
* COMPARING ALL OR PART OF TWO LOBS IDENTIFICATION DIVISION. PROGRAM-ID. COMPARE. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 BLOB1 SQL-BLOB. 01 BLOB2 SQL-BLOB. 01 BUFFER2 PIC X(32767) VARYING. 01 RET PIC S9(9) COMP. 01 AMT PIC S9(9) COMP. 01 POS PIC S9(9) COMP VALUE 1024. 01 OFFSET PIC S9(9) COMP VALUE 1. EXEC SQL VAR BUFFER2 IS VARRAW(32767) END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. COMPARE-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locators: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL ALLOCATE :BLOB2 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_COMPOSITE INTO :BLOB1 FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 2268 AND AD_ID = 21001 END-EXEC. EXEC SQL SELECT AD_COMPOSITE INTO :BLOB2 FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 3060 AND AD_ID = 11001 END-EXEC. * Open the BLOBs for READ ONLY: EXEC SQL LOB OPEN :BLOB1 READ ONLY END-EXEC. EXEC SQL LOB OPEN :BLOB2 READ ONLY END-EXEC. * Execute PL/SQL to get COMPARE functionality: MOVE 4 TO AMT. EXEC SQL EXECUTE BEGIN :RET := DBMS_LOB.COMPARE(:BLOB1,:BLOB2,:AMT,1,1); END; END-EXEC. IF RET = 0 * Logic for equal BLOBs goes here DISPLAY "BLOBs are equal" ELSE * Logic for unequal BLOBs goes here DISPLAY "BLOBs are not equal" END-IF. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. EXEC SQL LOB CLOSE :BLOB2 END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL FREE :BLOB2 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Comparing all or part of two LOBs #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void compareTwoLobs_proc() { OCIBlobLocator *Lob_loc1, *Lob_loc2; int Amount = 32767; int Retval; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate the LOB locators: */ EXEC SQL ALLOCATE :Lob_loc1; EXEC SQL ALLOCATE :Lob_loc2; /* Select the LOBs: */ EXEC SQL SELECT ad_composite INTO :Lob_loc1 FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; EXEC SQL SELECT ad_composite INTO :Lob_loc2 FROM Print_media WHERE product_id = 2056 AND ad_id = 12001; /* Opening the LOBs is Optional: */ EXEC SQL LOB OPEN :Lob_loc1 READ ONLY; EXEC SQL LOB OPEN :Lob_loc2 READ ONLY; /* Compare the two Frames using DBMS_LOB.COMPARE() from within PL/SQL: */ EXEC SQL EXECUTE BEGIN :Retval := DBMS_LOB.COMPARE(:Lob_loc1, :Lob_loc2, :Amount, 1, 1); END; END-EXEC; if (0 == Retval) printf("The frames are equal\n"); else printf("The frames are not equal\n"); /* Closing the LOBs is mandatory if you have opened them: */ EXEC SQL LOB CLOSE :Lob_loc1; EXEC SQL LOB CLOSE :Lob_loc2; /* Release resources held by the locators: */ EXEC SQL FREE :Lob_loc1; EXEC SQL FREE :Lob_loc2; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; compareTwoLobs_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Comparing all or part of two LOBs Dim MySession As OraSession Dim OraDb As OraDatabase Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Dim OraDyn as OraDynaset, OraAdPhoto1 as OraBLOB, OraAdPhotoClone as OraBLOB Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value 'Clone it for future reference Set OraAdPhotoClone = OraAdPhoto1.Clone 'Lets go to the next row and compare LOBs OraDyn.MoveNext MsgBox CBool(OraAdPhotot1.Compare(OraAdPhototClone, OraAdPhotoClone.size, 1, 1))
// Comparing all or part of two LOBs import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_87 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB lob_loc1 = null; BLOB lob_loc2 = null; ResultSet rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media WHERE product_id = 2056 AND ad_id = 12001"); if (rset.next()) { lob_loc1 = ((OracleResultSet)rset).getBLOB (1); } rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media WHERE product_id = 3106 AND ad_id = 13001"); if (rset.next()) { lob_loc2 = ((OracleResultSet)rset).getBLOB (1); } if (lob_loc1.length() > lob_loc2.length()) System.out.println ("Looking for LOB2 inside LOB1. result = " + Long.toString(lob_loc1.position(lob_loc2, 1))); else System.out.println("Looking for LOB1 inside LOB2. result = " + Long.toString(lob_loc2.position(lob_loc1, 1))); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to see if a pattern exists in the LOB (instr).
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The examples examine the advertisement text in the ad_sourcetext
column to see if the string "children" is present.
Examples are provided in the following programmatic environments:
/* Seeing if a pattern exists in the LOB using instr. The example procedure instringLOB_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE instringLOB_proc IS Lob_loc CLOB; Pattern VARCHAR2(30) := 'children'; Position INTEGER := 0; Offset INTEGER := 1; Occurrence INTEGER := 1; BEGIN /* Select the LOB: */ SELECT ad_sourcetext INTO Lob_loc FROM Print_media WHERE product_id = 2268 AND ad_id = 21001; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); /* Seek for the pattern: */ Position := DBMS_LOB.INSTR(Lob_loc, Pattern, Offset, Occurrence); IF Position = 0 THEN DBMS_OUTPUT.PUT_LINE('Pattern not found'); ELSE DBMS_OUTPUT.PUT_LINE('The pattern occurs at '|| position); END IF; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); END;
* SEEING IF A PATTERN EXISTS IN THE LOB USING INSTR IDENTIFICATION DIVISION. PROGRAM-ID. CLOB-INSTR. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 CLOB1 SQL-CLOB. 01 PATTERN PIC X(8) VALUE "children". 01 POS PIC S9(9) COMP. 01 OFFSET PIC S9(9) COMP VALUE 1. 01 OCCURRENCE PIC S9(9) COMP VALUE 1. 01 USERID PIC X(11) VALUES "SAMP/SAMP". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. CLOB-INSTR. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the CLOB locator: EXEC SQL ALLOCATE :CLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-CLOB END-EXEC. EXEC SQL SELECT AD_SOURCETEXT INTO :CLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 2268 AND AD_ID = 21001 END-EXEC. * Open the CLOB for READ ONLY: EXEC SQL LOB OPEN :CLOB1 READ ONLY END-EXEC. * Execute PL/SQL to get INSTR functionality: EXEC SQL EXECUTE BEGIN :POS := DBMS_LOB.INSTR(:CLOB1, :PATTERN,:OFFSET,:OCCURRENCE); END; END-EXEC. IF POS = 0 * Logic for pattern not found here DISPLAY "Pattern not found." ELSE * Pos contains position where pattern is found DISPLAY "Pattern found." END-IF. EXEC SQL LOB CLOSE :CLOB1 END-EXEC. END-OF-CLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :CLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Seeing if a pattern exists in the LOB using instr #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void instringLOB_proc() { OCIClobLocator *Lob_loc; char *Pattern = "The End"; int Position = 0; int Offset = 1; int Occurrence = 1; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_sourcetext INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; /* Opening the LOB is Optional: */ EXEC SQL LOB OPEN :Lob_loc; /* Seek the Pattern using DBMS_LOB.INSTR() in a PL/SQL block: */ EXEC SQL EXECUTE BEGIN :Position := DBMS_LOB.INSTR(:Lob_loc, :Pattern, :Offset, :Occurrence); END; END-EXEC; if (0 == Position) printf("Pattern not found\n"); else printf("The pattern occurs at %d\n", Position); /* Closing the LOB is mandatory if you have opened it: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "pm/pm"; EXEC SQL CONNECT :pm; instringLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
// Seeing if a pattern exists in the LMOB using instr import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_91 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "pm", "pm"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { final int offset = 1; // Start looking at the first byte final int occurrence = 1; // Start at the 1st occurrence of the pattern within the CLOB CLOB lob_loc = null; String pattern = new String("Junk"); // Pattern to look for within the CLOB. ResultSet rset = stmt.executeQuery ( "SELECT ad_sourcetext FROM Print_media WHERE product_id = 2268 AND ad_id = 21001"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getCLOB (1); } // Search for location of pattern string in the CLOB, starting at offset 1: long result = lob_loc.position(pattern, offset); System.out.println("Results of Pattern Comparison : " + Long.toString(result)); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to determine the length of a LOB.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
These examples demonstrate how to determine the length of the LOB
in the foreign language text (ad_fltextn
) column.
Examples are provided in the following programmatic environments:
/* Getting the length of a LOB. Example procedure getLengthLOB_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE getLengthLOB_proc IS Lob_loc NCLOB; Length INTEGER; BEGIN /* Select the LOB: */ SELECT ad_fltextn INTO Lob_loc FROM Print_media WHERE product_id = 3106 AND ad_id = 13001; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); /* Get the length of the LOB: */ length := DBMS_LOB.GETLENGTH(Lob_loc); IF length IS NULL THEN DBMS_OUTPUT.PUT_LINE('LOB is null.'); ELSE DBMS_OUTPUT.PUT_LINE('The length is '|| length); END IF; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); END;
/* Getting the length of a LOB /* Select the locator into a locator variable */ sb4 select_adfltextn_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIDefine *defnp1; text *sqlstmt = (text *)"SELECT ad_fltextn FROM Print_media WHERE product_id = 2268"; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Define the column being selected */ checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2)SQLT_CLOB,(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT)); /* Execute and fetch one row */ checkerr (errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } /* This function gets the length of the selected LOB */ void getLengthLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { ub4 length; OCILobLocator *Lob_loc; /* Allocate Locator resources */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select a LOB locator from FLSub */ printf(" select a adfltextn locator\n"); select_adfltextn_locator(Lob_loc, errhp, svchp, stmthp); /* Opening the LOB is Optional */ printf(" Open the locator (optional)\n"); checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READONLY))); printf(" get the length of ad_fltextn.\n"); checkerr (errhp, OCILobGetLength(svchp, errhp, Lob_loc, &length)); /* Length is undefined if the LOB is NULL or undefined */ fprintf(stderr," Length of LOB is %d\n",length); /* Closing the LOBs is Mandatory if they have been Opened */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
* GETTING THE LENGTH OF A LOB IDENTIFICATION DIVISION. PROGRAM-ID. LOB-LENGTH. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 CLOB1 SQL-CLOB. 01 LOB-ATTR-GRP. 05 LEN PIC S9(9) COMP. 01 D-LEN PIC 9(4). 01 USERID PIC X(11) VALUES "SAMP/SAMP". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. LOB-LENGTH. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the target CLOB: EXEC SQL ALLOCATE :CLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-CLOB END-EXEC. EXEC SQL SELECT AD_SOURCETEXT INTO :CLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 3060 AND AD_ID = 11001 END-EXEC. * Obtain the length of the CLOB: EXEC SQL LOB DESCRIBE :CLOB1 GET LENGTH INTO :LEN END-EXEC. MOVE LEN TO D-LEN. DISPLAY "The length is ", D-LEN. * Free the resources used by the CLOB: END-OF-CLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :CLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Getting the length of a LOB */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void getLengthLOB_proc() { OCIClobLocator *Lob_loc; unsigned int Length; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_sourcetext INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; /* Opening the LOB is Optional: */ EXEC SQL LOB OPEN :Lob_loc READ ONLY; /* Get the Length: */ EXEC SQL LOB DESCRIBE :Lob_loc GET LENGTH INTO :Length; /* If the LOB is NULL or unitialized, then Length is Undefined: */ printf("Length is %d characters\n", Length); /* Closing the LOB is mandatory if you have Opened it: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; getLengthLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Getting the length of a LOB Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value 'Display out size of the lob: MsgBox "Length of the lob is " & OraAdPhoto1.Size
//Getting the length of a LOB import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_95 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { CLOB lob_loc = null; ResultSet rset = stmt.executeQuery ("SELECT ad_sourcetext FROM Print_media WHERE product_id = 3106"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getCLOB (1); } System.out.println( "Length of this column is : " + Long.toString(lob_loc.length())); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to copy all or part of a LOB to another LOB.
Prior to updating a LOB
value using the PL/SQL DBMS_LOB
package or OCI, you must lock the row containing the LOB
. While the SQL INSERT
and UPDATE
statements implicitly lock the row, locking is done explicitly by means of a SQL SELECT
FOR
UPDATE
statement in SQL and PL/SQL programs, or by using an OCI
pin
or lock
function in OCI programs.
For more details on the state of the locator after an update, refer to "Updating LOBs Via Updated Locators" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. See the following syntax references for each programmatic environment:
The code in these examples shows you how to copy a portion of an image in the ad_photo
column to the ad_composite
column.
Examples are provided in the following programmatic environments:
/* Copying all or part of a LOB to another LOB. Example procedure copyLOB_proc is not part of DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE copyLOB_proc IS Dest_loc BLOB; Src_loc BLOB; Amount NUMBER; Dest_pos NUMBER; Src_pos NUMBER; BEGIN SELECT ad_composite INTO Dest_loc FROM Print_media WHERE product_id = 3106 AND ad_id = 13001 FOR UPDATE; /* Select the LOB: */ SELECT ad_photo INTO Src_loc FROM Print_media WHERE product_id = 2056 AND ad_id = 12001; /* Opening the LOBs is optional: */ DBMS_LOB.OPEN(Dest_loc, DBMS_LOB.LOB_READWRITE); DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY); /* Copies the LOB from the source position to the destination position: */ DBMS_LOB.COPY(Dest_loc, Src_loc, Amount, Dest_pos, Src_pos); /* Closing LOBs is mandatory if you have opened them: */ DBMS_LOB.CLOSE(Dest_loc); DBMS_LOB.CLOSE(Src_loc); COMMIT; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Operation failed'); END;
/* Copying all or part of a LOB to another LOB */ /* Select the locator */ sb4 select_photo_locator_2(Lob_loc, dest_type, errhp, svchp, stmthp) OCILobLocator *Lob_loc; ub1 dest_type; /* whether destination locator */ OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { char sqlstmt[150]; OCIDefine *defnp1; if (dest_type == TRUE) { strcpy (sqlstmt, (char *)"SELECT ad_photo FROM Print_media WHERE product_id=2268 FOR UPDATE"); printf (" select destination ad_photo locator\n"); } else { strcpy(sqlstmt, (char *)"SELECT ad_photo FROM Print_media WHERE product_ id=3106"); printf (" select source ad_photo locator\n"); } checkerr (errhp, OCIStmtPrepare(stmthp, errhp, (text *)sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } /* This function copies part of the Source LOB into a specified position in the destination LOB */ void copyAllPartLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIBlobLocator *Dest_loc, *Src_loc; int Amount = 1000; /* <Amount to Copy> */ int Dest_pos = 100; /*<Position to start copying into> */ int Src_pos = 1; /* <Position to start copying from> */ /* Allocate the LOB locators */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Dest_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Src_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the LOBs */ printf(" select the destination and source locators\n"); select_photo_locator_2(Dest_loc, TRUE, errhp, svchp, stmthp); /* destination locator */ select_photo_locator_2(Src_loc, FALSE, errhp, svchp, stmthp); /* source locator */ /* Opening the LOBs is Optional */ printf (" open the destination locator (optional)\n"); checkerr (errhp, OCILobOpen(svchp, errhp, Dest_loc, OCI_LOB_READWRITE)); printf (" open the source locator (optional)\n"); checkerr (errhp, OCILobOpen(svchp, errhp, Src_loc, OCI_LOB_READONLY)); printf (" copy the lob (amount) from the source to destination\n"); checkerr (errhp, OCILobCopy(svchp, errhp, Dest_loc, Src_loc, Amount, Dest_pos, Src_pos)); /* Closing the LOBs is Mandatory if they have been Opened */ printf(" close the locators\n"); checkerr (errhp, OCILobClose(svchp, errhp, Dest_loc)); checkerr (errhp, OCILobClose(svchp, errhp, Src_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Dest_loc, (ub4) OCI_DTYPE_LOB); (void) OCIDescriptorFree((dvoid *) Src_loc, (ub4) OCI_DTYPE_LOB); return; }
* COPYING ALL OR PART OF A LOB TO ANOTHER LOB IDENTIFICATION DIVISION. PROGRAM-ID. BLOB-COPY. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 DEST SQL-BLOB. 01 SRC SQL-BLOB. * Define the amount to copy. * This value has been chosen arbitrarily: 01 AMT PIC S9(9) COMP VALUE 10. * Define the source and destination position. * These values have been chosen arbitrarily: 01 SRC-POS PIC S9(9) COMP VALUE 1. 01 DEST-POS PIC S9(9) COMP VALUE 1. * The return value from PL/SQL function: 01 RET PIC S9(9) COMP. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. COPY-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locators: EXEC SQL ALLOCATE :DEST END-EXEC. EXEC SQL ALLOCATE :SRC END-EXEC. DISPLAY "Source and destination LOBs are open.". EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_PHOTO INTO :SRC FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 3106 AND AD_ID = 13001 END-EXEC. DISPLAY "Source LOB populated.". EXEC SQL SELECT AD_PHOTO INTO :DEST FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 3060 AND AD_ID = 11001 FOR UPDATE END-EXEC. DISPLAY "Destination LOB populated.". * Open the DESTination LOB read/write and SRC LOB read only EXEC SQL LOB OPEN :DEST READ WRITE END-EXEC. EXEC SQL LOB OPEN :SRC READ ONLY END-EXEC. DISPLAY "Source and destination LOBs are open.". * Copy the desired amount EXEC SQL LOB COPY :AMT FROM :SRC AT :SRC-POS TO :DEST AT :DEST-POS END-EXEC. DISPLAY "Src LOB copied to destination LOB.". * Execute PL/SQL to get COMPARE functionality * to make sure that the BLOBs are identical EXEC SQL EXECUTE BEGIN :RET := DBMS_LOB.COMPARE(:SRC,:DEST,:AMT,1,1); END; END-EXEC. IF RET = 0 * Logic for equal BLOBs goes here DISPLAY "BLOBs are equal" ELSE * Logic for unequal BLOBs goes here DISPLAY "BLOBs are not equal" END-IF. EXEC SQL LOB CLOSE :DEST END-EXEC. EXEC SQL LOB CLOSE :SRC END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :DEST END-EXEC. EXEC SQL FREE :SRC END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Copying all or part of a LOB to another LOB */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void copyLOB_proc() { OCIBlobLocator *Dest_loc, *Src_loc; int Amount = 5; int Dest_pos = 10; int Src_pos = 1; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate the LOB locators: */ EXEC SQL ALLOCATE :Dest_loc; EXEC SQL ALLOCATE :Src_loc; /* Select the LOBs: */ EXEC SQL SELECT ad_photo INTO :Dest_loc FROM Print_media WHERE product_id = 2268 AND AD_ID = 21001 FOR UPDATE; EXEC SQL SELECT ad_photo INTO :Src_loc FROM Print_media WHERE product_id = 2056 AND ad_id = 12001; /* Opening the LOBs is Optional: */ EXEC SQL LOB OPEN :Dest_loc READ WRITE; EXEC SQL LOB OPEN :Src_loc READ ONLY; /* Copies the specified Amount from the source position in the source LOB to the destination position in the destination LOB: */ EXEC SQL LOB COPY :Amount FROM :Src_loc AT :Src_pos TO :Dest_loc AT :Dest_pos; /* Closing the LOBs is mandatory if they have been opened: */ EXEC SQL LOB CLOSE :Dest_loc; EXEC SQL LOB CLOSE :Src_loc; /* Release resources held by the locators: */ EXEC SQL FREE :Dest_loc; EXEC SQL FREE :Src_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; copyLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Copying all or part of a LOB to another LOB Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value Set OraAdPhotoClone = OraAdPhoto1.Clone 'Go to next row and copy LOB OraDyn.MoveNext OraDyn.Edit OraAdPhoto1.Copy OraAdPhotoClone, OraAdPhotoClone.Size, 1, 1 OraDyn.Update
// Copying all or part of a LOB to another LOB import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_100 { public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { final int AMOUNT_TO_COPY = 2000; ResultSet rset = null; BLOB dest_loc = null; BLOB src_loc = null; InputStream in = null; OutputStream out = null; byte[] buf = new byte[AMOUNT_TO_COPY]; rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 3060 AND ad_ad = 11001"); if (rset.next()) { src_loc = ((OracleResultSet)rset).getBLOB (1); } in = src_loc.getBinaryStream(); rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 3106 AND ad_id = 13001 FOR UPDATE"); if (rset.next()) { dest_loc = ((OracleResultSet)rset).getBLOB (1); } out = dest_loc.getBinaryOutputStream(); // read AMOUNT_TO_COPY bytes into buf from stream, starting from offset 0: in.read(buf, 0, AMOUNT_TO_COPY); // write AMOUNT_TO_COPY bytes from buf into output stream, starting at offset 0: out.write(buf, 0, AMOUNT_TO_COPY); // Close all streams and handles in.close(); out.flush(); out.close(); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to copy a LOB locator.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
These examples show how to copy one locator to another involving the image (ad_composite
). Note how different locators may point to the same or different, current or outdated data.
Examples are provided in the following programmatic environments:
Note: Assigning one LOB to another using PL/SQL entails using the ":=" sign. This is an advanced topic that is discussed in more detail under the heading "Read Consistent Locators". |
/* Copying a LOB locator. Example procedure lobAssign_proc is not part of DBMS_LOB package. */ CREATE OR REPLACE PROCEDURE lobAssign_proc IS Lob_loc1 blob; Lob_loc2 blob; BEGIN SELECT ad_composite INTO Lob_loc1 FROM Print_media WHERE product_id = 3106 AND ad_id = 13001 FOR UPDATE; /* Assign Lob_loc1 to Lob_loc2 thereby saving a copy of the value of the lob at this point in time. */ Lob_loc2 := Lob_loc1; /* When you write some data to the lob through Lob_loc1, Lob_loc2 will not see the newly written data whereas Lob_loc1 will see the new data. */ END;
/* Copying a LOB locator */ /* Select the locator */ sb4 select_lock_adcomp_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_composite FROM Print_media WHERE product_id=3106 AND ad_id = 13001 FOR UPDATE"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return (0); } void assignLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *dest_loc, *src_loc; boolean isEqual; /* Allocate the LOB locators */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &dest_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &src_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the LOBs */ printf (" select and lock a frame locator\n"); select_lock_adcomp_locator(src_loc, errhp, svchp, stmthp);/* source locator */ /* Assign src_loc to dest_loc thereby saving a copy of the value of the LOB at this point in time. */ printf(" assign the src locator to dest locator\n"); checkerr (errhp, OCILobAssign(envhp, errhp, src_loc, &dest_loc)); /* When you write some data to the LOB through Lob_loc1, Lob_loc2 will not see the newly written data whereas Lob_loc1 will see the new data. */ /* Call OCI to see if the two locators are Equal */ printf (" check if Lobs are Equal.\n"); checkerr (errhp, OCILobIsEqual(envhp, src_loc, dest_loc, &isEqual)); if (isEqual) { /* ... The LOB locators are Equal */ printf(" Lob Locators are equal.\n"); } else { /* ... The LOB locators are not Equal */ printf(" Lob Locators are NOT Equal.\n"); } /* Note that in this example, the LOB locators will be Equal */ /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) dest_loc, (ub4) OCI_DTYPE_LOB); (void) OCIDescriptorFree((dvoid *) src_loc, (ub4) OCI_DTYPE_LOB); return; }
* COPYING A LOB LOCATOR IDENTIFICATION DIVISION. PROGRAM-ID. COPY-LOCATOR. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 DEST SQL-BLOB. 01 SRC SQL-BLOB. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. COPY-BLOB-LOCATOR. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locators: EXEC SQL ALLOCATE :DEST END-EXEC. EXEC SQL ALLOCATE :SRC END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_COMPOSITE INTO :SRC FROM PRINT_MEDIA WHERE PRODUCT_ID = 2268 AND AD_ID = 21001 FOR UPDATE END-EXEC. EXEC SQL LOB ASSIGN :SRC TO :DEST END-EXEC. * When you write data to the LOB through SRC, DEST will * not see the newly written data END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :DEST END-EXEC. EXEC SQL FREE :SRC END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Copying a LOB locator */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void lobAssign_proc() { OCIBlobLocator *Lob_loc1, *Lob_loc2; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc1; EXEC SQL ALLOCATE :Lob_loc2; EXEC SQL SELECT ad_composite INTO :Lob_loc1 FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Assign Lob_loc1 to Lob_loc2 thereby saving a copy of the value of the LOB at this point in time: */ EXEC SQL LOB ASSIGN :Lob_loc1 TO :Lob_loc2; /* When you write some data to the LOB through Lob_loc1, Lob_loc2 will not see the newly written data whereas Lob_loc1 will see the new data: */ } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; lobAssign_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Copying a LOB locator Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id ", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value Set OraAdPhotoClone = OraAdPhoto1.Clone OraDyn.MoveNext 'Copy 1000 bytes of LOB values OraAdPhotoClone to OraAdPhotol at OraAdPhotol 'offset 100: OraDyn.Edit OraAdPhoto1.Copy OraAdPhotoClone, 1000, 100 OraDyn.Update
// Copying a LOB locator import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_104 { public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB lob_loc1 = null; BLOB lob_loc2 = null; ResultSet rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media WHERE product_id = 2056 AND ad_id = 12001"); if (rset.next()) { lob_loc1 = ((OracleResultSet)rset).getBLOB (1); } // When you write data to LOB through lob_loc1,lob_loc2 will not see changes lob_loc2 = lob_loc1; stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to see if one LOB locator is equal to another.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
If two locators are equal, this means that they refer to the same version of the LOB data (see "Read Consistent Locators"). In this example, the locators are equal. However, it may be as important to determine that locators do not refer to same version of the LOB data.
Examples are provided in the following programmatic environments:
/* Seeing if One LOB locator is Equal to Another */ /* Select the locator: */ sb4 select_lock_adcomp_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_composite FROM Print_media WHERE product_id=2268 AND ad_id = 21001 FOR UPDATE"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row: */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return (0); } void locatorIsEqual(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *dest_loc, *src_loc; boolean isEqual; /* Allocate the LOB locators: */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &dest_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &src_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the LOBs: */ printf (" select and lock an ad_composite locator\n"); select_lock_adcomp_locator(src_loc, errhp, svchp, stmthp);/* source locator */ /* Assign src_loc to dest_loc thereby saving a copy of the value of the LOB at this point in time: */ printf(" assign the src locator to dest locator\n"); checkerr (errhp, OCILobAssign(envhp, errhp, src_loc, &dest_loc)); /* When you write some data to the LOB through Lob_loc1, Lob_loc2 will not see the newly written data whereas Lob_loc1 will see the new data: */ /* Call OCI to see if the two locators are Equal: */ printf (" check if Lobs are Equal.\n"); checkerr (errhp, OCILobIsEqual(envhp, src_loc, dest_loc, &isEqual)); if (isEqual) { /* ... The LOB locators are Equal: */ printf(" Lob Locators are equal.\n"); } else { /* ... The LOB locators are not Equal: */ printf(" Lob Locators are NOT Equal.\n"); } /* Note that in this example, the LOB locators will be Equal */ /* Free resources held by the locators: */ (void) OCIDescriptorFree((dvoid *) dest_loc, (ub4) OCI_DTYPE_LOB); (void) OCIDescriptorFree((dvoid *) src_loc, (ub4) OCI_DTYPE_LOB); return; }
/* Seeing if One LOB locator is equal to another */ /* Pro*C/C++ does not provide a mechanism to test the equality of two locators. But you can use OCI directly. Two locators can be compared to determine whether or not they are equal as this example demonstrates: */ #include <sql2oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void LobLocatorIsEqual_proc() { OCIBlobLocator *Lob_loc1, *Lob_loc2; OCIEnv *oeh; boolean isEqual; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc1; EXEC SQL ALLOCATE :Lob_loc2; EXEC SQL SELECT ad_composite INTO Lob_loc1 FROM Print_media where product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Assign Lob_loc1 to Lob_loc2 thereby saving a copy of the value of the LOB at this point in time: */ EXEC SQL LOB ASSIGN :Lob_loc1 TO :Lob_loc2; /* When you write some data to the lob through Lob_loc1, Lob_loc2 will not see the newly written data whereas Lob_loc1 will see the new data. */ /* Get the OCI Environment Handle using a SQLLIB Routine: */ (void) SQLEnvGet(SQL_SINGLE_RCTX, &oeh); /* Call OCI to see if the two locators are Equal: */ (void) OCILobIsEqual(oeh, Lob_loc1, Lob_loc2, &isEqual); if (isEqual) printf("The locators are equal\n"); else printf("The locators are not equal\n"); /* Note that in this example, the LOB locators will be Equal */ EXEC SQL FREE :Lob_loc1; EXEC SQL FREE :Lob_loc2; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; LobLocatorIsEqual_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
// Seeing if one LOB locator is equal to another import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_108 { public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB lob_loc1 = null; BLOB lob_loc2 = null; ResultSet rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 3106 AND ad_id = 13001"); if (rset.next()) { lob_loc1 = ((OracleResultSet)rset).getBLOB (1); } // When you write data to LOB through lob_loc1,lob_loc2 will not see the changes: lob_loc2 = lob_loc1; // Note that in this example, the Locators will be equal. if (lob_loc1.equals(lob_loc2)) { // The Locators are equal: System.out.println("Locators are equal"); } else { // The Locators are different: System.out.println("Locators are NOT equal"); } stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to see if a LOB locator is initialized.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The operation allows you to determine if the locator has been initialized or not. In the example shown both locators are found to be initialized.
Examples are provided in the following programmatic environments:
/* Seeing if a LOB locator is initialized */ /* Select the locator: */ sb4 select_adcomp_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_composite FROM Print_media WHERE product_id=2268 AND ad_id = 21001"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row: */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return (0); } void isInitializedLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc1, *Lob_loc2; boolean isInitialized; /* Allocate the LOB locators: */ printf(" allocate locator 1 and 2\n"); (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc1, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc2, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the LOBs: */ printf (" select an ad_composite locator into locator 1\n"); select_adcomp_locator(Lob_loc1, errhp, svchp, stmthp); /* locator 1 */ /* Determine if the locator 1 is Initialized -: */ checkerr(errhp, OCILobLocatorIsInit(envhp, errhp, Lob_loc1, &isInitialized)); /* IsInitialized should return TRUE here */ printf(" for Locator 1, isInitialized = %d\n", isInitialized); /* Determine if the locator 2 is Initialized -: */ checkerr(errhp, OCILobLocatorIsInit(envhp, errhp, Lob_loc2, &isInitialized)); /* IsInitialized should return FALSE here */ printf(" for Locator 2, isInitialized = %d\n", isInitialized); /* Free resources held by the locators: */ (void) OCIDescriptorFree((dvoid *) Lob_loc1, (ub4) OCI_DTYPE_LOB); (void) OCIDescriptorFree((dvoid *) Lob_loc2, (ub4) OCI_DTYPE_LOB); return; }
/* Seeing if a LOB locator is initialized */ /* Pro*C/C++ has no form of embedded SQL statement to determine if a LOB locator is initialized. Locators in Pro*C/C++ are initialized when they are allocated via the EXEC SQL ALLOCATE statement. An example can be written that uses embedded SQL and the OCI as is shown here: */ #include <sql2oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void LobLocatorIsInit_proc() { OCIBlobLocator *Lob_loc; OCIEnv *oeh; OCIError *err; boolean isInitialized; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_composite INTO Lob_loc FROM Print_media where product_id = 2056 AND ad_id = 12001; /* Get the OCI Environment Handle using a SQLLIB Routine: */ (void) SQLEnvGet(SQL_SINGLE_RCTX, &oeh); /* Allocate the OCI Error Handle: */ (void) OCIHandleAlloc((dvoid *)oeh, (dvoid **)&err, (ub4)OCI_HTYPE_ERROR, (ub4)0, (dvoid **)0); /* Use the OCI to determine if the locator is Initialized: */ (void) OCILobLocatorIsInit(oeh, err, Lob_loc, &isInitialized); if (isInitialized) printf("The locator is initialized\n"); else printf("The locator is not initialized\n"); /* Note that in this example, the locator is initialized */ /* Deallocate the OCI Error Handle: */ (void) OCIHandleFree(err, OCI_HTYPE_ERROR); /* Release resources held by the locator: */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; LobLocatorIsInit_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
This procedure describes how to determine the character set ID.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The use case demonstrates how to determine the character set ID of the foreign text (ad_fltextn
).
This functionality is currently available only in OCI:
/* Getting character set id */ /* This function takes a valid LOB locator and prints the character set id of the LOB. */ /* Select the locator */ sb4 select_adfltextn_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIDefine *defnp1; text *sqlstmt = (text *)"SELECT ad_fltextn FROM Print_media WHERE product_id = 2268 AND ad_id = 21001"; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Define the column being selected */ checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2)SQLT_CLOB,(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT)); /* Execute and fetch one row */ checkerr (errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } sb4 getcsidLob (envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc; ub2 charsetid =0 ; (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); printf (" select a ad_fltextn locator\n"); select_adfltextn_locator(Lob_loc, errhp, svchp, stmthp); printf (" get the character set id of adfltextn_locator\n"); /* Get the charactersid ID of the LOB*/ checkerr (errhp, OCILobCharSetId(envhp, errhp, Lob_loc, &charsetid)); printf(" character Set ID of ad_fltextn is : %d\n", charsetid); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
This procedure describes how to get the character set form.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The use case demonstrates how to determine the character set form of the foreign language text (ad_fltextn
).
This functionality is currently available only in OCI:
/* Getting character set form of the foreign language ad text, ad_fltextn */ /* Select the locator */ sb4 select_adfltextn_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIDefine *defnp1; text *sqlstmt = (text *)"SELECT ad_fltextn FROM Print_media WHERE product_id = 2268 AND ad_id = 21001"; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Define the column being selected */ checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2)SQLT_CLOB,(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT)); /* Execute and fetch one row */ checkerr (errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } /* This function takes a valid LOB locator and prints the character set form of the LOB. */ sb4 getcsformLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc; ub1 charset_form = 0 ; (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); printf (" select an ad_fltextn locator\n"); select_adfltextn_locator(Lob_loc, errhp, svchp, stmthp); printf (" get the character set form of ad_fltextn\n"); /* Get the charactersid form of the LOB*/ checkerr (errhp, OCILobCharSetForm(envhp, errhp, Lob_loc, &charset_form)); printf(" character Set Form of ad_fltextn is : %d\n", charset_form); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
This procedure describes how to append one LOB to another.
Prior to updating a LOB
value using the PL/SQL DBMS_LOB
package or the OCI, you must lock the row containing the LOB
. While the SQL INSERT
and UPDATE
statements implicitly lock the row, locking is done explicitly by means of a SQL SELECT
FOR
UPDATE
statement in SQL and PL/SQL programs, or by using an OCI
pin
or lock
function in OCI programs. For more details on the state of the locator after an update, refer to "Updating LOBs Via Updated Locators" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. See the following syntax references for each programmatic environment:
These examples append one image to another.
Examples are provided in the following programmatic environments:
/* Appending one LOB to another */ /* Note that the example procedure appendLOB_proc is not part of the DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE appendLOB_proc IS Dest_loc BLOB; Src_loc BLOB; BEGIN /* Select the LOB, get the destination LOB locator: */ SELECT ad_photo INTO Dest_loc FROM Print_media WHERE product_id = 2268 AND ad_id = 21001 FOR UPDATE; /* Select the LOB, get the destination LOB locator: */ SELECT ad_photo INTO Src_loc FROM Print_media WHERE product_id = 2056 AND ad_id = 12001; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Dest_loc, DBMS_LOB.LOB_READWRITE); DBMS_LOB.OPEN (Src_loc, DBMS_LOB.LOB_READONLY); DBMS_LOB.APPEND(Dest_loc, Src_loc); /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Dest_loc); DBMS_LOB.CLOSE (Src_loc); COMMIT; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Operation failed'); END;
/* Appending one LOB to another. */ /* This function appends the Source LOB to the end of the Destination LOB */ /* Select the locator */ sb4 select_lock_adphoto_locator_2(Lob_loc, dest_type, errhp, svchp, stmthp) OCILobLocator *Lob_loc; ub1 dest_type; /* whether destination locator */ OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { char sqlstmt[150]; OCIDefine *defnp1; if (dest_type == TRUE) { strcpy (sqlstmt, (char *)"SELECT ad_photo FROM Print_media WHERE product_id=2268 AND ad_id=21001 FOR UPDATE"); printf (" select destination ad_photo locator\n"); } else { strcpy(sqlstmt, (char *)"SELECT ad_photo FROM Print_media WHERE product_id=3106 and ad_id=13001"); printf (" select source ad_photo locator\n"); } checkerr (errhp, OCIStmtPrepare(stmthp, errhp, (text *)sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } void appendLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Dest_loc, *Src_loc; /* Allocate the LOB locators */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Dest_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Src_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the LOBs */ printf(" select source and destination Lobs\n"); select_lock_adphoto_locator_2(Dest_loc, TRUE, errhp, svchp, stmthp); /* destination locator */ select_lock_adphoto_locator_2(Src_loc, FALSE, errhp, svchp, stmthp); /* source locator */ /* Opening the LOBs is Optional */ checkerr (errhp, OCILobOpen(svchp, errhp, Dest_loc, OCI_LOB_READWRITE)); checkerr (errhp, OCILobOpen(svchp, errhp, Src_loc, OCI_LOB_READONLY)); /* Append Source LOB to the end of the Destination LOB. */ printf(" append the source Lob to the destination Lob\n"); checkerr(errhp, OCILobAppend(svchp, errhp, Dest_loc, Src_loc)); /* Closing the LOBs is Mandatory if they have been Opened */ checkerr (errhp, OCILobClose(svchp, errhp, Dest_loc)); checkerr (errhp, OCILobClose(svchp, errhp, Src_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Dest_loc, (ub4) OCI_DTYPE_LOB); (void) OCIDescriptorFree((dvoid *) Src_loc, (ub4) OCI_DTYPE_LOB); return; }
* APPENDING ONE LOB TO ANOTHER IDENTIFICATION DIVISION. PROGRAM-ID. LOB-APPEND. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 DEST SQL-BLOB. 01 SRC SQL-BLOB. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. APPEND-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locators: EXEC SQL ALLOCATE :DEST END-EXEC. EXEC SQL ALLOCATE :SRC END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_PHOTO INTO :DEST FROM PRINT_MEDIA WHERE PRODUCT_ID = 2268 AND AD_ID = 21001 FOR UPDATE END-EXEC. EXEC SQL SELECT AD_PHOTO INTO :SRC FROM PRINT_MEDIA WHERE PRODUCT_ID = 3060 AND AD_ID = 11001 END-EXEC. * Open the DESTination LOB read/write and SRC LOB read only: EXEC SQL LOB OPEN :DEST READ WRITE END-EXEC. EXEC SQL LOB OPEN :SRC READ ONLY END-EXEC. * Append the source LOB to the destination LOB: EXEC SQL LOB APPEND :SRC TO :DEST END-EXEC. EXEC SQL LOB CLOSE :DEST END-EXEC. EXEC SQL LOB CLOSE :SRC END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :DEST END-EXEC. EXEC SQL FREE :SRC END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Appending one LOB to another */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void appendLOB_proc() { OCIBlobLocator *Dest_loc, *Src_loc; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate the locators: */ EXEC SQL ALLOCATE :Dest_loc; EXEC SQL ALLOCATE :Src_loc; /* Select the destination locator: */ EXEC SQL SELECT Sound INTO :Dest_loc FROM Print_media WHERE product_id = 2268 AND ad_id = 21001 FOR UPDATE; /* Select the source locator: */ EXEC SQL SELECT Sound INTO :Src_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; /* Opening the LOBs is Optional: */ EXEC SQL LOB OPEN :Dest_loc READ WRITE; EXEC SQL LOB OPEN :Src_loc READ ONLY; /* Append the source LOB to the end of the destination LOB: */ EXEC SQL LOB APPEND :Src_loc TO :Dest_loc; /* Closing the LOBs is mandatory if they have been opened: */ EXEC SQL LOB CLOSE :Dest_loc; EXEC SQL LOB CLOSE :Src_loc; /* Release resources held by the locators: */ EXEC SQL FREE :Dest_loc; EXEC SQL FREE :Src_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; appendLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Appending one LOB to another Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value Set OraAdPhotoClone = OraAdPhoto1 OraDyn.MoveNext OraDyn.Edit OraAdPhoto1.Append OraAdPhotoClone OraDyn.Update
// Appending one LOB to another import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_121 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { ResultSet rset = null; BLOB dest_loc = null; BLOB src_loc = null; InputStream in = null; byte[] buf = new byte[MAXBUFSIZE]; int length = 0; long pos = 0; rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 2268 AND ad_id = 21001"); if (rset.next()) { src_loc = ((OracleResultSet)rset).getBLOB (1); } in = src_loc.getBinaryStream(); rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE"); if (rset.next()) { dest_loc = ((OracleResultSet)rset).getBLOB (1); } // Start writing at the end of the LOB. ie. append: pos = dest_loc.length(); while ((length = in.read(buf)) != -1) { // Write the contents of the buffer into position pos of the output LOB: dest_loc.putBytes(pos, buf); pos += length; } // Close all streams and handles: in.close(); stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to write to the end of (append-write to) a LOB.
The writeappend
operation writes a buffer to the end of a LOB.
For OCI, the buffer can be written to the LOB
in a single piece with this call; alternatively, it can be rendered piecewise using callbacks or a standard polling method.
If the value of the piece parameter is OCI_FIRST_PIECE
, data must be provided through callbacks or polling.
OCILobWriteAppend
() returns the OCI_NEED_DATA
error code. The application must call OCILobWriteAppend
() again to write more pieces of the LOB
. In this mode, the buffer pointer and the length can be different in each call if the pieces are of different sizes and from different locations. A piece value of OCI_LAST_PIECE
terminates the piecewise write.Prior to updating a LOB
value using the PL/SQL DBMS_LOB
package or the OCI, you must lock the row containing the LOB
. While the SQL INSERT
and UPDATE
statements implicitly lock the row, locking is done explicitly by means of an SQL SELECT
FOR
UPDATE
statement in SQL and PL/SQL programs, or by using an OCI
pin
or lock
function in OCI programs.
For more details on the state of the locator after an update, refer to "Updating LOBs Via Updated Locators" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
These examples demonstrate writing to the end of an image.
Examples are provided in the following programmatic environments:
/* Write-appending to a LOB /* Example procedure lobWriteAppend_proc is not part of DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE lobWriteAppend_proc IS Lob_loc BLOB; Buffer RAW(32767); Amount Binary_integer := 32767; BEGIN SELECT ad_composite INTO Lob_loc FROM Print_media WHERE product_id = 2056 AND ad_id = 12001 FOR UPDATE; /* Fill the buffer with data... */ /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE); /* Append the data from the buffer to the end of the LOB: */ DBMS_LOB.WRITEAPPEND(Lob_loc, Amount, Buffer); /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE(Lob_loc); END;
/* Write-appending to a LOB */ /* Select the locator into a locator variable: */ sb4 select_lock_adcomp_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_composite FROM Print_media WHERE product_id=2268 AND ad_id = 21001 FOR UPDATE"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row: */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return (0); } #define MAXBUFLEN 32767 void writeAppendLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIBlobLocator *Lob_loc; ub4 amt; ub4 offset; sword retval; ub1 bufp[MAXBUFLEN]; ub4 buflen; /* Allocate the locator: */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the BLOB: */ printf(" select and lock an ad-composite locator\n"); select_lock_adcomp_locator(Lob_loc, errhp, svchp, stmthp); /* Open the BLOB: */ checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READWRITE))); /* Setting the amt to the buffer length. Note here that amt is in bytes since we are using a BLOB: */ amt = sizeof(bufp); buflen = sizeof(bufp); /* Fill bufp with data: */ /* Write the data from the buffer at the end of the LOB: */ printf(" write-append data to the frame Lob\n"); checkerr (errhp, OCILobWriteAppend (svchp, errhp, Lob_loc, &amt, bufp, buflen, OCI_ONE_PIECE, (dvoid *)0, (sb4 (*)(dvoid *, dvoid *, ub4 *, ub1 *))0, 0, SQLCS_IMPLICIT)); /* Closing the BLOB is mandatory if you have opened it: */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators: */ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
* WRITE-APPENDING TO A LOB IDENTIFICATION DIVISION. PROGRAM-ID. WRITE-APPEND-BLOB. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 BLOB1 SQL-BLOB. 01 AMT PIC S9(9) COMP. 01 BUFFER PIC X(32767) VARYING. EXEC SQL VAR BUFFER IS LONG RAW (32767) END-EXEC. 01 USERID PIC X(11) VALUES "SAMP/SAMP". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. WRITE-APPEND-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locators: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_COMPOSITE INTO :BLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 3106 AND AD_ID = 13001 FOR UPDATE END-EXEC. * Open the target LOB: EXEC SQL LOB OPEN :BLOB1 READ WRITE END-EXEC. * Populate AMT here: MOVE 5 TO AMT. MOVE "2424242424" to BUFFER. * Append the source LOB to the destination LOB: EXEC SQL LOB WRITE APPEND :AMT FROM :BUFFER INTO :BLOB1 END-EXEC. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Write-appending to a LOB */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 128 void LobWriteAppend_proc() { OCIBlobLocator *Lob_loc; int Amount = BufferLength; /* Amount == BufferLength so only a single WRITE is needed: */ char Buffer[BufferLength]; /* Datatype equivalencing is mandatory for this datatype: */ EXEC SQL VAR Buffer IS RAW(BufferLength); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_composite INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Opening the LOB is Optional: */ EXEC SQL LOB OPEN :Lob_loc; memset((void *)Buffer, 1, BufferLength); /* Write the data from the buffer at the end of the LOB: */ EXEC SQL LOB WRITE APPEND :Amount FROM :Buffer INTO :Lob_loc; /* Closing the LOB is mandatory if it has been opened: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; LobWriteAppend_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
// Write-appending to a LOB import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_126 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB dest_loc = null; byte[] buf = new byte[MAXBUFSIZE]; long pos = 0; ResultSet rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media WHERE product_id = 2056 AND ad_id = 12001 FOR UPDATE"); if (rset.next()) { dest_loc = ((OracleResultSet)rset).getBLOB (1); } // Start writing at the end of the LOB. ie. append: pos = dest_loc.length(); // fill buf with contents to be written: buf = (new String("Hello World")).getBytes(); // Write the contents of the buffer into position pos of the output LOB: dest_loc.putBytes(pos, buf); // Close all streams and handles: stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to write data to a LOB.
The most efficient way to write large amounts of LOB data is to use OCILobWrite
() with the streaming mechanism enabled using polling or a callback. If you know how much data will be written to the LOB,
specify that amount when calling OCILobWrite
(). This will allow for the contiguity of the LOB
data on disk. Apart from being spatially efficient, the contiguous structure of the LOB
data will make for faster reads and writes in subsequent operations.
A chunk is one or more Oracle blocks. As noted previously, you can specify the chunk size for the LOB
when creating the table that contains the LOB
. This corresponds to the chunk size used by Oracle when accessing/modifying the LOB
value. Part of the chunk is used to store system-related information and the rest stores the LOB
value. The getchunksize
function returns the amount of space used in the LOB
chunk to store the LOB
value.
You will improve performance if you execute write
requests using a multiple of this chunk size. The reason for this is that the LOB
chunk is versioned for every write
operation. If all writes
are done on a chunk basis, no extra or excess versioning is incurred or duplicated. If it is appropriate for your application, you should batch writes until you have enough for an entire chunk instead of issuing several LOB
write calls that operate on the same LOB
chunk.
Prior to updating a LOB
value using the PL/SQL DBMS_LOB
package or OCI, you must lock the row containing the LOB
. While the SQL INSERT
and UPDATE
statements implicitly lock the row, locking is done explicitly by means of a SQL SELECT
FOR
UPDATE
statement in SQL and PL/SQL programs, or by using an OCI
pin
or lock
function in OCI programs.
For more details on the state of the locator after an update, refer to "Updating LOBs Via Updated Locators" in Chapter 5, "Large Objects: Advanced Topics".
When you are passing a hexadecimal string to DBMS_LOB.WRITE() to write data to a BLOB, use the following guidelines:
amount
parameter should be <= the buffer length
parameterlength
of the buffer should be ((amount
*2) - 1). This guideline exists because the two characters of the string are seen as one hexadecimal character (and an implicit hexadecimal-to-raw conversion takes place), that is, every two bytes of the string are converted to one raw byte.The following example is correct:
declare blob_loc BLOB; rawbuf RAW(10); an_offset INTEGER := 1; an_amount BINARY_INTEGER := 10; begin select blob_col into blob_loc from a_table where id = 1; rawbuf := '1234567890123456789'; dbms_lob.write(blob_loc, an_amount, an_offset, rawbuf); commit; end;
Replacing the value for 'an_amount' in the previous example with the following values, yields error message, ora_21560:
an_amount BINARY_INTEGER := 11;
or
an_amount BINARY_INTEGER := 19;
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The following examples allow the ad_sourcetext
data (the advertisement text) to be updated by writing data to the LOB
.
Examples are provided in the following programmatic environments:
/* Writing data to a LOB */ /* Example procedure writeDataToLOB_proc is not part of DBMS_LOB package. */ CREATE or REPLACE PROCEDURE writeDataToLOB_proc IS Lob_loc CLOB; Buffer VARCHAR2(32767); Amount BINARY_INTEGER := 32767; Position INTEGER := 1; i INTEGER; BEGIN /* Select a LOB: */ SELECT ad_sourcetext INTO Lob_loc FROM Print_media WHERE product_id = 2056 AND ad_id = 12001 FOR UPDATE; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE); /* Fill the buffer with data to write to the LOB: */ FOR i IN 1..3 LOOP DBMS_LOB.WRITE (Lob_loc, Amount, Position, Buffer); /* Fill the buffer with more data to write to the LOB: */ Position := Position + Amount; END LOOP; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); END; /* We add a second example to show a case in which the buffer size and amount differs from the first example: */ CREATE or REPLACE PROCEDURE writeDataToLOB_proc IS Lob_loc CLOB; Buffer VARCHAR2(32767); Amount BINARY_INTEGER := 32767; Position INTEGER; i INTEGER; Chunk_size INTEGER; BEGIN SELECT ad_sourcetext INTO Lob_loc FROM Print_media WHERE product_id = 2056 AND ad_id = 12001 FOR UPDATE; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE); Chunk_size := DBMS_LOB.GETCHUNKSIZE(Lob_loc); /* Fill the buffer with 'Chunk_size' worth of data to write to the LOB. Use the chunk size (or a multiple of chunk size) when writing data to the LOB. Make sure that you write within a chunk boundary and don't overlap different chunks within a single call to DBMS_LOB.WRITE. */ Amount := Chunk_size; /* Write data starting at the beginning of the second chunk: */ Position := Chunk_size + 1; FOR i IN 1..3 LOOP DBMS_LOB.WRITE (Lob_loc, Amount, Position, Buffer); /* Fill the buffer with more data (of size Chunk_size) to write to the LOB: */ Position := Position + Amount; END LOOP; /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); END;
/* Writing data to a LOB. Using OCI you can write arbitrary amounts of data to an Internal LOB in either a single piece or in multiple pieces using streaming with standard polling. A dynamically allocated Buffer holds the data being written to the LOB. */ /* Select the locator into a locator variable */ sb4 select_lock_adsourcetext_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *) "SELECT ad_sourcetext FROM Print_media pm \ WHERE pm.product_id = 2268 ANd ad_id = 21001 FOR UPDATE"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_CLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return (0); } #define MAXBUFLEN 32767 void writeDataToLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCIClobLocator *Lob_loc; ub4 Total = 2.5*MAXBUFLEN; /* <total amount of data to write to the CLOB in bytes> */ unsigned int amt; unsigned int offset; unsigned int remainder, nbytes; boolean last; ub1 bufp[MAXBUFLEN]; sb4 err; /* Allocate the locators desriptors*/ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the CLOB */ printf (" select an ad_source_text Lob\n"); select_lock_adsourcetext_locator(Lob_loc, errhp, svchp, stmthp); /* Open the CLOB */ checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READWRITE))); if (Total > MAXBUFLEN) nbytes = MAXBUFLEN; /* We will use streaming via standard polling */ else nbytes = Total; /* Only a single write is required */ /* Fill the buffer with nbytes worth of data */ remainder = Total - nbytes; /* Setting Amount to 0 streams the data until use specifies OCI_LAST_PIECE */ amt = 0; offset = 1; printf(" write the Lob data in pieces\n"); if (0 == remainder) { amt = nbytes; /* Here, (Total <= MAXBUFLEN ) so we can write in one piece */ checkerr (errhp, OCILobWrite (svchp, errhp, Lob_loc, &amt, offset, bufp, nbytes, OCI_ONE_PIECE, (dvoid *)0, (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, 0, SQLCS_IMPLICIT)); } else { /* Here (Total > MAXBUFLEN ) so we use streaming via standard polling */ /* write the first piece. Specifying first initiates polling. */ err = OCILobWrite (svchp, errhp, Lob_loc, &amt, offset, bufp, nbytes, OCI_FIRST_PIECE, (dvoid *)0, (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, 0, SQLCS_IMPLICIT); if (err != OCI_NEED_DATA) checkerr (errhp, err); last = FALSE; /* Write the next (interim) and last pieces */ do { if (remainder > MAXBUFLEN) nbytes = MAXBUFLEN; /* Still have more pieces to go */ else { nbytes = remainder; /* Here, (remainder <= MAXBUFLEN) */ last = TRUE; /* This is going to be the final piece */ } /* Fill the Buffer with nbytes worth of data */ if (last) { /* Specifying LAST terminates polling */ err = OCILobWrite (svchp, errhp, Lob_loc, &amt, offset, bufp, nbytes, OCI_LAST_PIECE, (dvoid *)0, (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, 0, SQLCS_IMPLICIT); if (err != OCI_SUCCESS) checkerr(errhp, err); } else { err = OCILobWrite (svchp, errhp, Lob_loc, &amt, offset, bufp, nbytes, OCI_NEXT_PIECE, (dvoid *)0, (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, 0, SQLCS_IMPLICIT); if (err != OCI_NEED_DATA) checkerr (errhp, err); } /* Determine how much is left to write */ remainder = remainder - nbytes; } while (!last); } /* At this point, (remainder == 0) */ /* Closing the LOB is mandatory if you have opened it */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
* WRITING DATA TO A LOB IDENTIFICATION DIVISION. PROGRAM-ID. WRITE-CLOB. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INFILE ASSIGN TO "datfile.dat" ORGANIZATION IS SEQUENTIAL. DATA DIVISION. FILE SECTION. FD INFILE RECORD CONTAINS 5 CHARACTERS. 01 INREC PIC X(5). WORKING-STORAGE SECTION. 01 CLOB1 SQL-CLOB. 01 BUFFER PIC X(5) VARYING. 01 AMT PIC S9(9) COMP VALUES 321. 01 OFFSET PIC S9(9) COMP VALUE 1. 01 END-OF-FILE PIC X(1) VALUES "N". 01 D-BUFFER-LEN PIC 9. 01 D-AMT PIC 9. 01 USERID PIC X(11) VALUES "SAMP/SAMP". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. WRITE-CLOB. EXEC SQL WHENEVER SQLERROR GOTO SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Open the input file: OPEN INPUT INFILE. * Allocate and initialize the CLOB locator: EXEC SQL ALLOCATE :CLOB1 END-EXEC. EXEC SQL SELECT AD_SOURCETEXT INTO :CLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 3106 AND AD_ID = 13001 FOR UPDATE END-EXEC. * Either write entire record or write first piece * Read a data file here and populate BUFFER-ARR and BUFFER-LEN * END-OF-FILE will be set to "Y" when the entire file has been * read. PERFORM READ-NEXT-RECORD. MOVE INREC TO BUFFER-ARR. MOVE 5 TO BUFFER-LEN. IF (END-OF-FILE = "Y") EXEC SQL LOB WRITE ONE :AMT FROM :BUFFER INTO :CLOB1 AT :OFFSET END-EXEC ELSE DISPLAY "LOB WRITE FIRST: ", BUFFER-ARR EXEC SQL LOB WRITE FIRST :AMT FROM :BUFFER INTO :CLOB1 AT :OFFSET END-EXEC. * Continue reading from the input data file * and writing to the CLOB: PERFORM READ-NEXT-RECORD. PERFORM WRITE-TO-CLOB UNTIL END-OF-FILE = "Y". MOVE INREC TO BUFFER-ARR. MOVE 1 TO BUFFER-LEN. DISPLAY "LOB WRITE LAST: ", BUFFER-ARR(1:BUFFER-LEN). EXEC SQL LOB WRITE LAST :AMT FROM :BUFFER INTO :CLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. WRITE-TO-CLOB. IF ( END-OF-FILE = "N") MOVE INREC TO BUFFER-ARR. MOVE 5 TO BUFFER-LEN. DISPLAY "LOB WRITE NEXT: ", BUFFER-ARR(1:BUFFER-LEN). EXEC SQL LOB WRITE NEXT :AMT FROM :BUFFER INTO :CLOB1 END-EXEC. PERFORM READ-NEXT-RECORD. READ-NEXT-RECORD. MOVE SPACES TO INREC. READ INFILE NEXT RECORD AT END MOVE "Y" TO END-OF-FILE. DISPLAY "END-OF-FILE IS " END-OF-FILE. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Writing data to a LOB */ /* This example shows how you can use Pro*C/C++ to write arbitrary amounts of data to an Internal LOB in either a single piece of in multiple pieces using a Streaming Mechanism that utilizes standard polling. A dynamically allocated Buffer holds the data being written to the LOB: */ #include <oci.h> #include <stdio.h> #include <string.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 1024 void writeDataToLOB_proc(multiple) int multiple; { OCIClobLocator *Lob_loc; varchar Buffer[BufferLength]; unsigned int Total; unsigned int Amount; unsigned int remainder, nbytes; boolean last; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate and Initialize the Locator: */ EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_sourcetext INTO Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Open the CLOB: */ EXEC SQL LOB OPEN :Lob_loc READ WRITE; Total = Amount = (multiple * BufferLength); if (Total > BufferLength) nbytes = BufferLength; /* We will use streaming via standard polling */ else nbytes = Total; /* Only a single write is required */ /* Fill the buffer with nbytes worth of data: */ memset((void *)Buffer.arr, 32, nbytes); Buffer.len = nbytes; /* Set the Length */ remainder = Total - nbytes; if (0 == remainder) { /* Here, (Total <= BufferLength) so we can write in one piece: */ EXEC SQL LOB WRITE ONE :Amount FROM :Buffer INTO :Lob_loc; printf("Write ONE Total of %d characters\n", Amount); } else { /* Here (Total > BufferLength) so we streaming via standard polling */ /* write the first piece. Specifying first initiates polling: */ EXEC SQL LOB WRITE FIRST :Amount FROM :Buffer INTO :Lob_loc; printf("Write first %d characters\n", Buffer.len); last = FALSE; /* Write the next (interim) and last pieces: */ do { if (remainder > BufferLength) nbytes = BufferLength; /* Still have more pieces to go */ else { nbytes = remainder; /* Here, (remainder <= BufferLength) */ last = TRUE; /* This is going to be the Final piece */ } /* Fill the buffer with nbytes worth of data: */ memset((void *)Buffer.arr, 32, nbytes); Buffer.len = nbytes; /* Set the Length */ if (last) { EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Specifying LAST terminates polling: */ EXEC SQL LOB WRITE LAST :Amount FROM :Buffer INTO :Lob_loc; printf("Write LAST Total of %d characters\n", Amount); } else { EXEC SQL WHENEVER SQLERROR DO break; EXEC SQL LOB WRITE NEXT :Amount FROM :Buffer INTO :Lob_loc; printf("Write NEXT %d characters\n", Buffer.len); } /* Determine how much is left to write: */ remainder = remainder - nbytes; } while (!last); } EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* At this point, (Amount == Total), the total amount that was written */ /* Close the CLOB: */ EXEC SQL LOB CLOSE :Lob_loc; /* Free resources held by the Locator: */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; writeDataToLOB_proc(1); EXEC SQL ROLLBACK WORK; writeDataToLOB_proc(4); EXEC SQL ROLLBACK WORK RELEASE; }
'Writing data to a LOB 'There are two ways of writing a lob, with orablob.write or orablob.copyfromfile 'Using the OraBlob.Write mechanism Dim OraDyn As OraDynaset, OraAdPhoto As OraBlob, amount_written%, chunksize%, curchunk() As Byte chunksize = 32767 Set OraDyn = OraDb.CreateDynaset("SELECT * FROM Print_media", ORADYN_DEFAULT) Set OraAdPhoto = OraDyn.Fields("ad_photo").Value fnum = FreeFile Open "c:\tmp\keyboard_3106_13001" For Binary As #fnum OraAdPhoto.offset = 1 OraAdPhoto.pollingAmount = LOF(fnum) remainder = LOF(fnum) Dim piece As Byte Get #fnum, , curchunk OraDyn.Edit piece = ORALOB_FIRST_PIECE OraAdPhoto.Write curchunk, chunksize, ORALOB_FIRST_PIECE While OraAdPhoto.Status = ORALOB_NEED_DATA remainder = remainder - chunksize If remainder <= chunksize Then chunksize = remainder piece = ORALOB_LAST_PIECE Else piece = ORALOB_NEXT_PIECE End If Get #fnum, , curchunk OraAdPhoto.Write curchunk, chunksize, piece Wend OraDyn.Update 'Using the OraBlob.CopyFromFile mechanism Set OraDyn = OraDb.CreateDynaset("select * from Print_media", ORADYN_DEFAULT) Set OraAdPhoto = OraDyn.Fields("ad_photo").Value Oradyn.Edit OraAdPhoto.CopyFromFile "c:\keyboardphoto3106.jpg" Oradyn.Update
//Writing data to a LOB import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_126 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB dest_loc = null; byte[] buf = new byte[MAXBUFSIZE]; long pos = 0; ResultSet rset = stmt.executeQuery ( "SELECT ad_composite FROM Print_media WHERE product_id = 2056 AND ad_id = 12001 FOR UPDATE"); if (rset.next()) { dest_loc = ((OracleResultSet)rset).getBLOB (1); } // Start writing at the end of the LOB. ie. append: pos = dest_loc.length(); // fill buf with contents to be written: buf = (new String("Hello World")).getBytes(); // Write the contents of the buffer into position pos of the output LOB: dest_loc.putBytes(pos, buf); // Close all streams and handles: stmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to trim LOB data.
Prior to updating a LOB
value using the PL/SQL DBMS_LOB
package, or OCI, you must lock the row containing the LOB
. While the SQL INSERT
and UPDATE
statements implicitly lock the row, locking is done explicitly by means of:
SELECT
FOR
UPDATE
statement in SQL and PL/SQL programs.OCI
pin
or lock
function in OCI programs.For more details on the state of the locator after an update, refer to "Updating LOBs Via Updated Locators" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
Unless otherwise noted, these examples access text (CLOB
data) referenced in the ad_finaltext
column of table Adheader_typ
, and trim it.
Examples are provided in the following programmatic environments:
/* Trimming LOB data */ /* Example procedure trimLOB_proc is not part of DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE trimLOB_proc IS Lob_loc CLOB; BEGIN /* Select the LOB, get the LOB locator: */ SELECT pm.Adheader_typ.ad_finaltext INTO Lob_loc FROM Print_media pm WHERE pm.product_id = 2056 AND pm.ad_id = 12001 FOR UPDATE; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE); /* Trim the LOB data: */ DBMS_LOB.TRIM(Lob_loc,100); /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); COMMIT; /* Exception handling: */ EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Operation failed'); END;
/* Trimming LOB data /* Select the locator into a locator variable */ sb4 select_lock_adfinaltext_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *) "SELECT pm.ad_finaltext \ FROM Print_media pm WHERE pm.product_id = 2268 AND ad_id = 21001 FOR UPDATE"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_CLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } void trimLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc; unsigned int trimLength; (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the CLOB */ printf( " select an ad_finaltext LOB\n"); select_lock_adfinaltext_locator(Lob_loc, errhp, svchp, stmthp); /* Open the CLOB */ checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READWRITE))); /* Trim the LOB to its new length */ trimLength = 100; /* <New truncated length of the LOB>*/ printf (" trim the lob to %d bytes\n", trimLength); checkerr (errhp, OCILobTrim (svchp, errhp, Lob_loc, trimLength )); /* Closing the CLOB is mandatory if you have opened it */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators*/ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); }
* Trimming LOB data IDENTIFICATION DIVISION. PROGRAM-ID. TRIM-CLOB. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 CLOB1 SQL-CLOB. 01 NEW-LEN PIC S9(9) COMP. * Define the source and destination position and location: 01 SRC-POS PIC S9(9) COMP. 01 DEST-POS PIC S9(9) COMP. 01 SRC-LOC PIC S9(9) COMP. 01 DEST-LOC PIC S9(9) COMP. 01 USERID PIC X(11) VALUES "SAMP/SAMP". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. TRIM-CLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the CLOB locators: EXEC SQL ALLOCATE :CLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-CLOB END-EXEC. EXEC SQL SELECT PM.AD_SOURCETEXT INTO :CLOB1 FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 3060 AND AD_ID = 11001 FOR UPDATE END-EXEC. * Open the CLOB: EXEC SQL LOB OPEN :CLOB1 READ WRITE END-EXEC. * Move some value to NEW-LEN: MOVE 3 TO NEW-LEN. EXEC SQL LOB TRIM :CLOB1 TO :NEW-LEN END-EXEC. EXEC SQL LOB CLOSE :CLOB1 END-EXEC. END-OF-CLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :CLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Trimming LOB data */ #include "pers_trim.h" #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("sqlcode = %ld\n", sqlca.sqlcode); printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void trimLOB_proc() { voiced_typ_ref *vt_ref; voiced_typ *vt_typ; OCIClobLocator *Lob_loc; unsigned int Length, trimLength; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL ALLOCATE :vt_ref; EXEC SQL ALLOCATE :vt_typ; /* Retrieve the REF using Associative SQL */ EXEC SQL SELECT PMtab.ad_sourctext INTO :vt_ref FROM Print_media PMtab WHERE PMtab.product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Dereference the Object using the Navigational Interface */ EXEC SQL OBJECT DEREF :vt_ref INTO :vt_typ FOR UPDATE; Lob_loc = vt_typ->script; /* Opening the LOB is Optional */ EXEC SQL LOB OPEN :Lob_loc READ WRITE; EXEC SQL LOB DESCRIBE :Lob_loc GET LENGTH INTO :Length; printf("Old length was %d\n", Length); trimLength = (unsigned int)(Length / 2); /* Trim the LOB to its new length */ EXEC SQL LOB TRIM :Lob_loc TO :trimLength; /* Closing the LOB is mandatory if it has been opened */ EXEC SQL LOB CLOSE :Lob_loc; /* Mark the Object as Modified (Dirty) */ EXEC SQL OBJECT UPDATE :vt_typ; /* Flush the changes to the LOB in the Object Cache */ EXEC SQL OBJECT FLUSH :vt_typ; /* Display the new (modified) length */ EXEC SQL SELECT Mtab.Voiced_ref.Script INTO :Lob_loc FROM Multimedia_tab Mtab WHERE Mtab.Clip_ID = 2; EXEC SQL LOB DESCRIBE :Lob_loc GET LENGTH INTO :Length; printf("New length is now %d\n", Length); /* Free the Objects and the LOB Locator */ EXEC SQL FREE :vt_ref; EXEC SQL FREE :vt_typ; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; trimLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Trimming LOB data Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value OraDyn.Edit OraAdPhoto1.Trim 10 OraDyn.Update
// Trimming BLOBs and CLOBs. // You need to import the java.sql package to use JDBC import java.sql.*; // You need to import the oracle.sql package to use oracle.sql.BLOB import oracle.sql.*; class TrimLob { public static void main (String args []) throws SQLException { // Load the Oracle JDBC driver DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); String url = "jdbc:oracle:oci8:@"; try { String url1 = System.getProperty("JDBC_URL"); if (url1 != null) url = url1; } catch (Exception e) { // If there is any security exception, ignore it // and use the default } // Connect to the database Connection conn = DriverManager.getConnection (url, "pm", "pm"); // It's faster when auto commit is off conn.setAutoCommit (false); // Create a Statement Statement stmt = conn.createStatement (); try { stmt.execute ("drop table basic_lob_table"); } catch (SQLException e) { // An exception could be raised here if the table did not exist already. } // Create a table containing a BLOB and a CLOB stmt.execute ("create table basic_lob_table (x varchar2 (30), b blob, c clob)"); // Populate the table stmt.execute ("insert into basic_lob_table values ('one', '010101010101010101010101010101', 'onetwothreefour')"); // Select the lobs ResultSet rset = stmt.executeQuery ("select * from basic_lob_table"); while (rset.next ()) { // Get the lobs BLOB blob = (BLOB) rset.getObject (2); CLOB clob = (CLOB) rset.getObject (3); // Show the original lob length System.out.println ("Open the lobs"); System.out.println ("blob.length()="+blob.length()); System.out.println ("clob.length()="+clob.length()); // Trim the lobs System.out.println ("Trim the lob to length = 6"); blob.trim (6); clob.trim (6); // Show the lob length after trim() System.out.println ("Open the lobs"); System.out.println ("blob.length()="+blob.length()); System.out.println ("clob.length()="+clob.length()); } // Close the ResultSet rset.close (); // Close the Statement stmt.close (); // Close the connection conn.close (); } }
Here is the old way of trimming LOB data, using DBMS_LOB.trim
:
// Trimming LOB data // Java IO classes: import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_141 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { CLOB lob_loc = null; ResultSet rset = stmt.executeQuery ( "SELECT pm.ad_finaltext FROM Print_media pm WHERE pm.product_id = 2056 AND ad_id = 12001 FOR UPDATE"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getCLOB (1); } // Open the LOB for READWRITE: OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall ("BEGIN DBMS_LOB.OPEN(?,DBMS_LOB.LOB_READWRITE); END;"); cstmt.setCLOB(1, lob_loc); cstmt.execute(); // Trim the LOB to length of 400: cstmt = (OracleCallableStatement) conn.prepareCall ("BEGIN DBMS_LOB.TRIM(?, 400); END;"); cstmt.setCLOB(1, lob_loc); cstmt.execute(); // Close the LOB: cstmt = (OracleCallableStatement) conn.prepareCall ( "BEGIN DBMS_LOB.CLOSE(?); END;"); cstmt.setCLOB(1, lob_loc); cstmt.execute(); stmt.close(); cstmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to erase part of a LOB.
Prior to updating a LOB
value using the PL/SQL DBMS_LOB
package or OCI, you must lock the row containing the LOB
. While INSERT
and UPDATE
statements implicitly lock the row, locking is done explicitly by means of a SELECT
FOR
UPDATE
statement in SQL and PL/SQL programs, or by using the OCI
pin
or lock
function in OCI programs.
For more details on the state of the locator after an update, refer to "Updating LOBs Via Updated Locators" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
The examples demonstrate erasing a portion of the image (ad_photo
).
Examples are provided in the following programmatic environments:
/* Erasing part of a LOB. Example procedure eraseLOB_proc is not part of DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE eraseLOB_proc IS Lob_loc BLOB; Amount INTEGER := 3000; BEGIN /* Select the LOB, get the LOB locator: */ SELECT ad_photo INTO lob_loc FROM Print_media WHERE product_id = 3106 AND ad_id = 13001 FOR UPDATE; /* Opening the LOB is optional: */ DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE); /* Erase the data: */ DBMS_LOB.ERASE(Lob_loc, Amount, 2000); /* Closing the LOB is mandatory if you have opened it: */ DBMS_LOB.CLOSE (Lob_loc); COMMIT; /* Exception handling: */ EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Operation failed'); END;
/* Erasing part of a LOB (persistent LOBs) Select the locator into a locator variable: */ sb4 select_lock_adphoto_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_photo FROM Print_media WHERE product_id=3060 AND ad_id = 11001 FOR UPDATE"; OCIDefine *defnp1, *defnp2; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) || OCIDefineByPos(stmthp, &defnp2, errhp, (ub4) 2, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT) ); /* Execute the select and fetch one row: */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } void eraseLob(envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc; ub4 amount = 3000; ub4 offset = 2000; OCILobLocator *Lob_Loc; (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the CLOB: */ printf( " select and lock an ad_photo LOB\n"); select_lock_adphoto_locator(Lob_loc, errhp, svchp, stmthp); /* Open the BLOB: */ checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READWRITE))); /* Erase the data starting at the specified Offset: */ printf(" erase %d bytes from the ad_photo Lob\n", amount); checkerr (errhp, OCILobErase (svchp, errhp, Lob_loc, &amount, offset )); /* Closing the BLOB is mandatory if you have opened it: */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators: */ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
* ERASING PART OF A LOB IDENTIFICATION DIVISION. PROGRAM-ID. ERASE-BLOB. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 BLOB1 SQL-BLOB. 01 AMT PIC S9(9) COMP. 01 OFFSET PIC S9(9) COMP. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. ERASE-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locators: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_PHOTO INTO :BLOB1 FROM PRINT_MEDIA PM WHERE PM.PRODUCT_ID = 2268 AND AD_ID = 21001 FOR UPDATE END-EXEC. * Open the BLOB: EXEC SQL LOB OPEN :BLOB1 READ WRITE END-EXEC. * Move some value to AMT and OFFSET: MOVE 2 TO AMT. MOVE 1 TO OFFSET. EXEC SQL LOB ERASE :AMT FROM :BLOB1 AT :OFFSET END-EXEC. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Erasing part of a LOB */ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void eraseLob_proc() { OCIBlobLocator *Lob_loc; int Amount = 5; int Offset = 5; EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_composite INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Opening the LOB is Optional: */ EXEC SQL LOB OPEN :Lob_loc READ WRITE; /* Erase the data starting at the specified Offset: */ EXEC SQL LOB ERASE :Amount FROM :Lob_loc AT :Offset; printf("Erased %d bytes\n", Amount); /* Closing the LOB is mandatory if it has been opened: */ EXEC SQL LOB CLOSE :Lob_loc; EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; eraseLob_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Erasing part of a LOB Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset("SELECT * FROM Print_media ORDER BY product_ id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value 'Erase 10 bytes begining from the 100th byte: OraDyn.Edit OraAdPhoto1.Erase 10, 100 OraDyn.Update
// Erasing part of a LOB import java.io.InputStream; import java.io.OutputStream; // Core JDBC classes: import java.sql.DriverManager; import java.sql.Connection; import java.sql.Types; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_145 { static final int MAXBUFSIZE = 32767; public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { BLOB lob_loc = null; int eraseAmount = 30; ResultSet rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 2056 AND ad_id = 12001 FOR UPDATE"); if (rset.next()) { lob_loc = ((OracleResultSet)rset).getBLOB (1); } // Open the LOB for READWRITE: OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall ("BEGIN DBMS_LOB.OPEN(?, " +"DBMS_LOB.LOB_READWRITE); END;"); cstmt.setBLOB(1, lob_loc); cstmt.execute(); // Erase eraseAmount bytes starting at offset 2000: cstmt = (OracleCallableStatement) conn.prepareCall ("BEGIN DBMS_LOB.ERASE(?, ?, 1); END;"); cstmt.registerOutParameter (1, OracleTypes.BLOB); cstmt.registerOutParameter (2, Types.INTEGER); cstmt.setBLOB(1, lob_loc); cstmt.setInt(2, eraseAmount); cstmt.execute(); lob_loc = cstmt.getBLOB(1); eraseAmount = cstmt.getInt(2); // Close the LOB: cstmt = (OracleCallableStatement) conn.prepareCall ( "BEGIN DBMS_LOB.CLOSE(?); END;"); cstmt.setBLOB(1, lob_loc); cstmt.execute(); conn.commit(); stmt.close(); cstmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to enable LOB buffering.
Enable buffering when performing a small read or write of data. Once you have completed these tasks, you must disable buffering before you can continue with any other LOB
operations.
Note:
|
For more information, refer to "LOB Buffering Subsystem" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
This scenario is part of the management of a buffering example related to ad_photo
that is developed in this and related methods.
Examples are provided in the following programmatic environments:
See:
This is executed in a similar way to that described in the example, "Disabling LOB Buffering". |
* ENABLING LOB BUFFERING IDENTIFICATION DIVISION. PROGRAM-ID. LOB-BUFFERING. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 BLOB1 SQL-BLOB. 01 BUFFER PIC X(10). 01 AMT PIC S9(9) COMP. EXEC SQL VAR BUFFER IS RAW(10) END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. LOB-BUFFERING. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locator: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT ad_photo INTO :BLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 3060 AND AD_ID = 11001 FOR UPDATE END-EXEC. * Open the BLOB and enable buffering: EXEC SQL LOB OPEN :BLOB1 READ WRITE END-EXEC. EXEC SQL LOB ENABLE BUFFERING :BLOB1 END-EXEC. * Write some data to the BLOB: MOVE "242424" TO BUFFER. MOVE 3 TO AMT. EXEC SQL LOB WRITE :AMT FROM :BUFFER INTO :BLOB1 END-EXEC. MOVE "212121" TO BUFFER. MOVE 3 TO AMT. EXEC SQL LOB WRITE :AMT FROM :BUFFER INTO :BLOB1 END-EXEC. * Now flush the buffered writes: EXEC SQL LOB FLUSH BUFFER :BLOB1 END-EXEC. EXEC SQL LOB DISABLE BUFFERING :BLOB1 END-EXEC. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Enabling LOB buffering #include <oci.h> #include <stdio.h> #include <string.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 256 void enableBufferingLOB_proc() { OCIBlobLocator *Lob_loc; int Amount = BufferLength; int multiple, Position = 1; /* Datatype equivalencing is mandatory for this datatype: */ char Buffer[BufferLength]; EXEC SQL VAR Buffer is RAW(BufferLength); EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate and Initialize the LOB: */ EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_composite INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Enable use of the LOB Buffering Subsystem: */ EXEC SQL LOB ENABLE BUFFERING :Lob_loc; memset((void *)Buffer, 0, BufferLength); for (multiple = 0; multiple < 8; multiple++) { /* Write data to the LOB: */ EXEC SQL LOB WRITE ONE :Amount FROM :Buffer INTO :Lob_loc AT :Position; Position += BufferLength; } /* Flush the contents of the buffers and Free their resources: */ EXEC SQL LOB FLUSH BUFFER :Lob_loc FREE; /* Turn off use of the LOB Buffering Subsystem: */ EXEC SQL LOB DISABLE BUFFERING :Lob_loc; /* Release resources held by the Locator: */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; enableBufferingLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Enabling LOB buffering (persistent LOBs) Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value 'Enable buffering: OraAdPhoto1.EnableBuffering
This procedure describes how to flush the LOB buffer.
Enable buffering when performing a small read or write of data. Once you have completed these tasks, you must disable buffering before you can continue with any other LOB
operations.
Notes:
|
For more information, refer to "LOB Buffering Subsystem" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
This scenario is part of the management of a buffering example related to ad_photo
that is developed in this and related methods.
Examples are provided in the following programmatic environments:
See:
Flushing the Buffer in OCI is executed in a similar fashion to that described in the example, "Disabling LOB Buffering". |
* Flushing the LOB buffer (persistent LOBs) IDENTIFICATION DIVISION. PROGRAM-ID. LOB-BUFFERING. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 BLOB1 SQL-BLOB. 01 BUFFER PIC X(10). 01 AMT PIC S9(9) COMP. EXEC SQL VAR BUFFER IS RAW(10) END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. LOB-BUFFERING. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locator: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_PHOTO INTO :BLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 2056 AND AD_ID = 12001 FOR UPDATE END-EXEC. * Open the BLOB and enable buffering: EXEC SQL LOB OPEN :BLOB1 READ WRITE END-EXEC. EXEC SQL LOB ENABLE BUFFERING :BLOB1 END-EXEC. * Write some data to the BLOB: MOVE "242424" TO BUFFER. MOVE 3 TO AMT. EXEC SQL LOB WRITE :AMT FROM :BUFFER INTO :BLOB1 END-EXEC. MOVE "212121" TO BUFFER. MOVE 3 TO AMT. EXEC SQL LOB WRITE :AMT FROM :BUFFER INTO :BLOB1 END-EXEC. * Now flush the buffered writes: EXEC SQL LOB FLUSH BUFFER :BLOB1 END-EXEC. EXEC SQL LOB DISABLE BUFFERING :BLOB1 END-EXEC. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Flushing the LOB Buffer (persistent LOBs) #include <oci.h> #include <stdio.h> #include <string.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 256 void flushBufferingLOB_proc() { OCIBlobLocator *Lob_loc; int Amount = BufferLength; int multiple, Position = 1; /* Datatype equivalencing is mandatory for this datatype: */ char Buffer[BufferLength]; EXEC SQL VAR Buffer is RAW(BufferLength); EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate and Initialize the LOB: */ EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT Sound INTO :Lob_loc FROM Multimedia_tab WHERE Clip_ID = 1 FOR UPDATE; /* Enable use of the LOB Buffering Subsystem: */ EXEC SQL LOB ENABLE BUFFERING :Lob_loc; memset((void *)Buffer, 0, BufferLength); for (multiple = 0; multiple < 8; multiple++) { /* Write data to the LOB: */ EXEC SQL LOB WRITE ONE :Amount FROM :Buffer INTO :Lob_loc AT :Position; Position += BufferLength; } /* Flush the contents of the buffers and Free their resources: */ EXEC SQL LOB FLUSH BUFFER :Lob_loc FREE; /* Turn off use of the LOB Buffering Subsystem: */ EXEC SQL LOB DISABLE BUFFERING :Lob_loc; /* Release resources held by the Locator: */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; flushBufferingLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
This procedure describes how to disable LOB buffering.
Enable buffering when performing a small read or write of data. Once you have completed these tasks, you must disable buffering before you can continue with any other LOB
operations.
Note:
|
For more information, refer to "LOB Buffering Subsystem" in Chapter 5, "Large Objects: Advanced Topics".
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
This scenario is part of the management of a buffering example related to ad_photo
that is developed in this and related methods.
Examples are provided in the following programmatic environments:
/* Disabling LOB buffering (persistent LOBs) */ /* Select the locator into a locator variable: */ sb4 select_lock_adphoto_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_photo FROM Print_media WHERE product_id=3060 FOR UPDATE"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row: */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } #define MAXBUFLEN 32767 void lobBuffering (envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { OCILobLocator *Lob_loc; ub4 amt; ub4 offset; sword retval; ub1 bufp[MAXBUFLEN]; ub4 buflen; /* Allocate the locator desriptor: */ (void) OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); /* Select the BLOB: */ printf (" select an ad_photo Lob\n"); select_lock_adphoto_locator(Lob_loc, errhp, svchp, stmthp); /* Open the BLOB: */ checkerr (errhp, (OCILobOpen(svchp, errhp, Lob_loc, OCI_LOB_READWRITE))); /* Enable LOB Buffering: */ printf (" enable LOB buffering\n"); checkerr (errhp, OCILobEnableBuffering(svchp, errhp, Lob_loc)); printf (" write data to LOB\n"); /* Write data into the LOB: */ amt = sizeof(bufp); buflen = sizeof(bufp); offset = 1; checkerr (errhp, OCILobWrite (svchp, errhp, Lob_loc, &amt, offset, bufp, buflen, OCI_ONE_PIECE, (dvoid *)0, (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, 0, SQLCS_IMPLICIT)); /* Flush the buffer: */ printf(" flush the LOB buffers\n"); checkerr (errhp, OCILobFlushBuffer(svchp, errhp, Lob_loc, (ub4)OCI_LOB_BUFFER_FREE)); /* Disable Buffering: */ printf (" disable LOB buffering\n"); checkerr (errhp, OCILobDisableBuffering(svchp, errhp, Lob_loc)); /* Subsequent LOB WRITEs will not use the LOB Buffering Subsystem: */ /* Closing the BLOB is mandatory if you have opened it: */ checkerr (errhp, OCILobClose(svchp, errhp, Lob_loc)); /* Free resources held by the locators: */ (void) OCIDescriptorFree((dvoid *) Lob_loc, (ub4) OCI_DTYPE_LOB); return; }
* DISABLING LOB BUFFERING (PERSISTENT LOBS) IDENTIFICATION DIVISION. PROGRAM-ID. LOB-BUFFERING. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERID PIC X(11) VALUES "SAMP/SAMP". 01 BLOB1 SQL-BLOB. 01 BUFFER PIC X(10). 01 AMT PIC S9(9) COMP. EXEC SQL VAR BUFFER IS RAW(10) END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. LOB-BUFFERING. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locator: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT SOUND INTO :BLOB1 FROM MULTIMEDIA_TAB WHERE CLIP_ID = 1 FOR UPDATE END-EXEC. * Open the BLOB and enable buffering: EXEC SQL LOB OPEN :BLOB1 READ WRITE END-EXEC. EXEC SQL LOB ENABLE BUFFERING :BLOB1 END-EXEC. * Write some data to the BLOB: MOVE "242424" TO BUFFER. MOVE 3 TO AMT. EXEC SQL LOB WRITE :AMT FROM :BUFFER INTO :BLOB1 END-EXEC. MOVE "212121" TO BUFFER. MOVE 3 TO AMT. EXEC SQL LOB WRITE :AMT FROM :BUFFER INTO :BLOB1 END-EXEC. * Now flush the buffered writes: EXEC SQL LOB FLUSH BUFFER :BLOB1 END-EXEC. EXEC SQL LOB DISABLE BUFFERING :BLOB1 END-EXEC. EXEC SQL LOB CLOSE :BLOB1 END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Disabling LOB buffering (persistent LOBs) */ #include <oci.h> #include <stdio.h> #include <string.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } #define BufferLength 256 void disableBufferingLOB_proc() { OCIBlobLocator *Lob_loc; int Amount = BufferLength; int multiple, Position = 1; /* Datatype equivalencing is mandatory for this datatype: */ char Buffer[BufferLength]; EXEC SQL VAR Buffer is RAW(BufferLength); EXEC SQL WHENEVER SQLERROR DO Sample_Error(); /* Allocate and Initialize the LOB: */ EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_photo INTO :Lob_loc FROM Print_media WHERE product_id = 3060 AND ad_id = 11001 FOR UPDATE; /* Enable use of the LOB Buffering Subsystem: */ EXEC SQL LOB ENABLE BUFFERING :Lob_loc; memset((void *)Buffer, 0, BufferLength); for (multiple = 0; multiple < 7; multiple++) { /* Write data to the LOB: */ EXEC SQL LOB WRITE ONE :Amount FROM :Buffer INTO :Lob_loc AT :Position; Position += BufferLength; } /* Flush the contents of the buffers and Free their resources: */ EXEC SQL LOB FLUSH BUFFER :Lob_loc FREE; /* Turn off use of the LOB Buffering Subsystem: */ EXEC SQL LOB DISABLE BUFFERING :Lob_loc; /* Write APPEND can only be done when Buffering is Disabled: */ EXEC SQL LOB WRITE APPEND ONE :Amount FROM :Buffer INTO :Lob_loc; /* Release resources held by the Locator: */ EXEC SQL FREE :Lob_loc; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; disableBufferingLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Disabling LOB buffering (persistent LOBs) Dim MySession As OraSession Dim OraDb As OraDatabase Dim OraDyn As OraDynaset, OraAdPhoto1 As OraBlob, OraAdPhotoClone As OraBlob Set MySession = CreateObject("OracleInProcServer.XOraSession") Set OraDb = MySession.OpenDatabase("exampledb", "samp/samp", 0&) Set OraDyn = OraDb.CreateDynaset( "SELECT * FROM Print_media ORDER BY product_id, ad_id", ORADYN_DEFAULT) Set OraAdPhoto1 = OraDyn.Fields("ad_photo").Value 'Disable buffering: OraAdPhoto1.DisableBuffering
For information on how to UPDATE a LOB when binds of more than 4,000 bytes are involved, see the following sections in Chapter 7, "Modeling and Design":
This procedure describes how to UPDATE a LOB with EMPTY_CLOB() or EMPTY_BLOB().
Before you write data to an internal LOB
, make the LOB
column non-null; that is, the LOB column must contain a locator that points to an empty or populated LOB
value. You can initialize a BLOB
column's value by using the function EMPTY_BLOB
() as a default predicate. Similarly, a CLOB
or NCLOB
column's value can be initialized by using the function EMPTY_CLOB
().
You can also initialize a LOB column with a character or raw string less than 4,000 bytes in size. For example:
UPDATE Print_media SET ad_sourcetext = 'This is a One Line Story' WHERE product_id = 2268;
You can perform this initialization during CREATE
TABLE
(see "Creating a Table Containing One or More LOB Columns") or, as in this case, by means of an INSERT
.
Use the following syntax reference:
The following example shows a series of updates using the EMPTY_CLOB operation to different data types.
The example is provided in SQL and applies to all the programmatic environments:
UPDATE Print_media SET ad_sourcetext = EMPTY_CLOB() WHERE product_id = 3060 AND ad_id = 11001; UPDATE Print_media SET ad_fltextn = EMPTY_CLOB() WHERE product_id = 3060 AND ad_id = 11001; UPDATE Print_media SET ad_photo = EMPTY_BLOB() WHERE product_id = 3060 AND ad_id = 11001;
This procedure describes how to use UPDATE as SELECT with LOBs.
Not applicable.
Use the following syntax reference:
This example updates data from online_media
by means of a reference:
The SQL example provided applies to all programmatic environments:
Rem Updating a row by selecting a LOB from another table (persistent LOBs) UPDATE Print_media SET ad_sourcetext = (SELECT * product_text FROM online_media WHERE product_id = 3060); WHERE product_id = 3060 AND ad_id = 11001;
This procedure describes how to UPDATE by initializing a LOB locator bind variable.
Not applicable.
See Chapter 3, "LOB Support in Different Programmatic Environments" for a list of available functions in each programmatic environment. Use the following syntax references for each programmatic environment:
These examples update ad_photo
data by means of a locator bind variable.
Examples are provided in the following programmatic environments:
/* Updating a LOB by initializing a LOB locator bind variable */ /* Example procedure updateUseBindVariable_proc is not part of DBMS_LOB package: */ CREATE OR REPLACE PROCEDURE updateUseBindVariable_proc (Lob_loc BLOB) IS BEGIN UPDATE Print_media SET ad_photo = lob_loc WHERE product_id = 3060 AND ad_id = 11001; END; DECLARE Lob_loc BLOB; BEGIN /* Select the LOB: */ SELECT ad_photo INTO Lob_loc FROM Print_media WHERE product-id = 3060 AND ad_id = 11001; updateUseBindVariable_proc (Lob_loc); COMMIT; END;
/* Updating a LOB by initializing a LOB locator bind variable (persistent LOBs) */ /* Select the locator into a locator variable: */ sb4 select_adphoto_locator(Lob_loc, errhp, svchp, stmthp) OCILobLocator *Lob_loc; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *sqlstmt = (text *)"SELECT ad_photo FROM Print_media WHERE product_id=2268"; OCIDefine *defnp1; checkerr (errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4)strlen((char *)sqlstmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1, (dvoid *)&Lob_loc, (sb4)0, (ub2) SQLT_BLOB,(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT)); /* Execute the select and fetch one row: */ checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return 0; } /* Update the LOB in the selected row in the table: */ void updateLobUsingBind (envhp, errhp, svchp, stmthp) OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; { text *updstmt = (text *) "UPDATE Print_media SET ad_photo = :1 WHERE product_id = 3106"; OCILobLocator *Lob_loc; OCIBind *bndhp1; /* Allocate locator resources: */ (void) OCIDescriptorAlloc((dvoid *)envhp, (dvoid **)&Lob_loc, (ub4)OCI_DTYPE_LOB, (size_t)0, (dvoid **)0); /* Select the locator: */ printf(" select an ad_photo locator\n"); (void)select_adphoto_locator(Lob_loc, errhp, svchp, stmthp); /* Prepare the SQL statement: */ checkerr (errhp, OCIStmtPrepare(stmthp, errhp, updstmt, (ub4) strlen((char *) updstmt), (ub4) OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Binds the bind positions: */ printf(" bind locator to bind position\n"); checkerr (errhp, OCIBindByPos(stmthp, &bndhp1, errhp, (ub4) 1, (dvoid *) &Lob_loc, (sb4)0, SQLT_BLOB, (dvoid *) 0, (ub2 *)0, (ub2 *)0, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT)); /* Execute the SQL statement: */ printf ("update LOB column in another row using this locator\n"); checkerr (errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)); return; }
* Updating a LOB by initializing a LOB locator bind variable * [Example script: 3806.pco] IDENTIFICATION DIVISION. PROGRAM-ID. UPDATE-BLOB. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 BLOB1 SQL-BLOB. 01 NEW-LEN PIC S9(9) COMP. 01 AMT PIC S9(9) COMP. 01 OFFSET PIC S9(9) COMP. * Define the source and destination position and location: 01 SRC-POS PIC S9(9) COMP. 01 DEST-POS PIC S9(9) COMP. 01 SRC-LOC PIC S9(9) COMP. 01 DEST-LOC PIC S9(9) COMP. 01 USERID PIC X(11) VALUES "SAMP/SAMP". EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. UPDATE-BLOB. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERID END-EXEC. * Allocate and initialize the BLOB locators: EXEC SQL ALLOCATE :BLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-BLOB END-EXEC. EXEC SQL SELECT AD_PHOTO INTO :BLOB1 FROM PRINT_MEDIA WHERE PRODUCT_ID = 2056 AND AD_ID = 12001 END-EXEC. EXEC SQL UPDATE PRINT_MEDIA SET AD_PHOTO = :BLOB1 WHERE PRODUCT_ID = 2268 AND AD_ID = 21001 END-EXEC. END-OF-BLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :BLOB1 END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.
/* Updating a LOB by initializing a LOB locator bind variable (persistent LOBs)*/ #include <oci.h> #include <stdio.h> #include <sqlca.h> void Sample_Error() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } void updateUseBindVariable_proc(Lob_loc) OCIBlobLocator *Lob_loc; { EXEC SQL WHENEVER SQLERROR DO Sample_Error(); EXEC SQL UPDATE Print_media SET ad_photo = :Lob_loc WHERE product_id = 2268; } void updateLOB_proc() { OCIBlobLocator *Lob_loc; EXEC SQL ALLOCATE :Lob_loc; EXEC SQL SELECT ad_photo INTO :Lob_loc FROM Print_media WHERE product_id = 3060; updateUseBindVariable_proc(Lob_loc); EXEC SQL FREE :Lob_loc; EXEC SQL COMMIT WORK; } void main() { char *samp = "samp/samp"; EXEC SQL CONNECT :samp; updateLOB_proc(); EXEC SQL ROLLBACK WORK RELEASE; }
'Updating a LOB by initializing a LOB locator bind variable (persistent LOBs) Dim OraDyn As OraDynaset, OraAdPhoto as OraBlob 'Select a column with product_id = 3106: Set OraDyn = OraDb.CreateDynaset("SELECT * FROM Print_media WHERE product_id= 3106", ORADYN_DEFAULT) 'Get the OraBlob object from the field: Set OraAdPhoto = OraDyn.Fields("AD_PHOTO").Value 'Create a parameter for OraBlob object: OraDb.Parameters.Add "AD_PHOTO",Null,ORAPARM_INPUT,ORATYPE_BLOB 'Set the value of ad_photo parameter to OraAdPhoto: OraDb.Parameters("AD_PHOTO").Value = OraAdPhoto 'Update table Print_media with OraAdPhoto for product_id = 2268: OraDb.ExecuteSQL("Update Print_media SET ad_photo = :AD_PHOTO WHERE product_id = 2268")
// Updating a LOB by initializing a LOB locator bind variable (persistent LOBs) import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // Oracle Specific JDBC classes: import oracle.sql.*; import oracle.jdbc.driver.*; public class Ex2_163 { public static void main (String args []) throws Exception { // Load the Oracle JDBC driver: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Connect to the database: Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@", "samp", "samp"); // It's faster when auto commit is off: conn.setAutoCommit (false); // Create a Statement: Statement stmt = conn.createStatement (); try { ResultSet rset = stmt.executeQuery ( "SELECT ad_photo FROM Print_media WHERE product_id = 3106 AND ad_id = 13001"); if (rset.next()) { // retrieve the LOB locator from the ResultSet: BLOB photo_blob = ((OracleResultSet)rset).getBLOB (1); OraclePreparedStatement ops = (OraclePreparedStatement) conn.prepareStatement( "UPDATE Print_media SET ad_photo = ? WHERE product_id = 2056 AND ad_id = 12001"); ops.setBlob(1, photo_blob); ops.execute(); rset.close(); stmt.close(); conn.commit(); conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
This procedure describes how to delete the row of a table containing a LOB.
To delete a row that contains an internal LOB
column or attribute use one of the following commands
In either case you delete the LOB
locator and the LOB value as well.
Note: Due to the consistent read mechanism, the old |
Of course, two distinct rows of a table with a LOB
column have their own distinct LOB
locators and distinct copies of the LOB
values irrespective of whether the LOB
values are the same or different. This means that deleting one row has no effect on the data or LOB
locator in another row even if one LOB
was originally copied from another row.
Use the following syntax reference:
In the following example, all data associated with the product having product_id = 3060 AND ad_id 11001
is deleted.
The SQL example provide applies to all programmatic environments:
DELETE FROM Print_media WHERE product_id = 3060 AND ad_id = 11001; TRUNCATE TABLE Print_media; DROP TABLE Print_media;
|
Copyright © 1996, 2002 Oracle Corporation. All Rights Reserved. |
|