4.2 BFILE Locators
For BFILE
s, the value is stored in a server-side operating system file, in other words, BFILE
s are external to the database. The BFILE
locator that refers to the file is stored in the database row.
BFILE
, first create a DIRECTORY
object that is an alias for the full path name to the operating system file. Then, you can initialize an instance of BFILE
type, using the BFILENAME
function in SQL or PL/SQL, or OCILobFileSetName()
in OCI. You can use this BFILE
instance in one of the following ways:
- If your need for a particular
BFILE
is temporary and limited within the module on which you are working, then you can assign thisBFILE
instance to a PL/SQL or OCI local variable of typeBFILE
. Subsequently, you can use theBFILE
related APIs on this variable without having to associate this with a column in the database. TheBFILE
API operations on a temporary instance are executed on the client side, without any round-trips to the server. - You can insert a persistent reference to a
BFILE
in theBFILE
column using anINSERT
orUPDATE
statement. Before using SQL to insert or update a row with aBFILE
, you must initialize theBFILE
variable to eitherNULL
or aDIRECTORY
object name and file name.Note:
TheOCISetAttr()
function does not allow you to set aBFILE
locator toNULL
. To insert aNULL BFILE
in OCI, you must set the bind value toNULL
.
It is possible to have multiple BFILE
columns in the same record or
different records referring to the same file. For example, the following
UPDATE
statements set the BFILE
column of the row
with key_value = 21
in lob_table
to point to the same
file as the row with key_value = 22
.
UPDATE lob_table SET f_lob = (SELECT f_lob FROM lob_table WHERE key_value = 22) WHERE
key_value = 21;
See Also:
Loading BFILEs with SQL*LoaderBFILEs in Objects
If you are using BFILE
s in objects, you must first set the BFILE
value, and then flush the object to the database. So, you must first call the OCIObjectNew()
function, followed by the OCILobFileSetName()
function and the OCIObjectFlush()
function respectively.
BFILEs in Shared Server (Multithreaded Server) Mode
The database does not support session migration for BFILE
data types
in shared server (multithreaded server) mode. This implies that in shared server
sessions, BFILE
operations are bound to one shared server, they
cannot migrate from one server to another, and open BFILE
instances
can persist beyond the end of a call to a shared server.
Examples of Creating Directory Objects and BFILE Locators
Many examples in the following sections use the print_media
table.
Following is the structure of the table:
Figure 4-1 print_media table
Example 4-1 Inserting BFILEs in SQL and PL/SQL
conn system/manager
-- The DBA creates DIRECTORY object and grants READ to the user
create or replace directory MYDIR as '/your/directory/path/here';
GRANT read ON DIRECTORY MYDIR TO pm;
conn pm/pm
-- Use BFILENAME to create a BFILE locator for INSERT
INSERT INTO print_media
(product_id, ad_id, ad_composite, ad_sourcetext, ad_graphic)
VALUES
(1, 1, empty_blob(), empty_clob(), BFILENAME('MYDIR','file1.txt'));
-- After this statement, 2 rows point to the same BFILE
INSERT INTO print_media
(product_id, ad_id, ad_composite, ad_sourcetext, ad_graphic)
select 2, ad_id, ad_composite, ad_sourcetext, ad_graphic from print_media;
-- Update the 2nd row to point to a different file
UPDATE print_media SET ad_graphic = BFILENAME('MYDIR','file2.txt') WHERE product_id =2;
-- Insert a 3rd row with invalid file name
INSERT INTO print_media
(product_id, ad_id, ad_composite, ad_sourcetext, ad_graphic)
VALUES
(3, 3, empty_blob(), empty_clob(), BFILENAME('MYDIR','file_does_not_exist.txt'));
-- Insert a NULL for BFILE
INSERT INTO print_media
(product_id, ad_id, ad_composite, ad_sourcetext, ad_graphic)
VALUES
(4, 4, empty_blob(), empty_clob(), NULL);
-- Inserting in PLSQL using a BFILE variable
DECLARE
f BFILE;
BEGIN
f := BFILENAME('MYDIR','file5.txt');
INSERT INTO print_media (product_id, ad_id, ad_composite, ad_sourcetext, ad_graphic)
VALUES (5, 5, NULL, NULL, f);
END;
/
SELECT product_id, ad_id, ad_graphic FROM print_media ORDER BY 1,2;
Example 4-2 Inserting BFILEs in OCI
STATIC TEXT *insstmt = "INSERT INTO print_media (product_id, ad_id, ad_graphic) VALUES (:1, :1, :2)";
sword insert_bfile()
{
OCILobLocator *f = (OCILobLocator *)0;
OCIStmt *stmthp;
OCIBind *bndp1 = (OCIBind *) 0;
OCIBind *bndp2 = (OCIBind *) 0;
ub4 id;
CHECK_ERROR (OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/*************** Allocate descriptor ***********************/
CHECK_ERROR (OCIDescriptorAlloc((dvoid *) envhp, (dvoid **) &f,
(ub4)OCI_DTYPE_FILE, (size_t) 0,
(dvoid **) 0));
/********** Execute insstmt to insert f ********************/
id = 6;
CHECK_ERROR (OCILobFileSetName(envhp, errhp, &f,
(text*)"MYDIR", sizeof("MYDIR") -1,
(text*)"file6.txt",
sizeof("file6.txt") -1));
CHECK_ERROR (OCIStmtPrepare(stmthp, errhp, insstmt,
(ub4) strlen((char *) insstmt),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
CHECK_ERROR (OCIBindByPos(stmthp, &bndp1, errhp, (ub4) 1, (dvoid *) &id,
(sb4) sizeof(id), SQLT_INT, (dvoid *) 0, (ub2 *) 0,
(ub2 *)0, (ub4) 0, (ub4*) 0, (ub4) OCI_DEFAULT));
CHECK_ERROR (OCIBindByPos(stmthp, &bndp2, errhp, (ub4) 2, (dvoid *) &f4,
(sb4) -1, SQLT_BFILE, (dvoid *) 0, (ub2 *) 0,
(ub2 *)0, (ub4) 0, (ub4*) 0, (ub4) OCI_DEFAULT));
CHECK_ERROR (OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DEFAULT));
/********** Execute insstmt to insert NULL ********************/
id = 7;
CHECK_ERROR (OCIStmtPrepare(stmthp, errhp, insstmt,
(ub4) strlen((char *) insstmt),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
CHECK_ERROR (OCIBindByPos(stmthp, &bndp1, errhp, (ub4) 1, (dvoid *) &id,
(sb4) sizeof(id), SQLT_INT, (dvoid *) 0, (ub2 *) 0,
(ub2 *)0, (ub4) 0, (ub4*) 0, (ub4) OCI_DEFAULT));
CHECK_ERROR (OCIBindByPos(stmthp, &bndp2, errhp, (ub4) 2, (dvoid *) NULL,
(sb4) -1, SQLT_BFILE, (dvoid *) 0, (ub2 *) 0,
(ub2 *)0, (ub4) 0, (ub4*) 0, (ub4) OCI_DEFAULT));
CHECK_ERROR (OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DEFAULT));
}