出典: IT Computer Tutorial
Oracle を使用したことがある人なら誰でも、Oracle には可変長の文字列を表すために使用される VARCHAR2 というデータ型があることを知っています。 VARCHAR2 は、Oracle が推奨するタイプでもあります。しかし、VARCHAR2 の使用には問題があります。VARCHAR2 は最大 4000 文字しか表現できず、これは中国語の 2000 文字に相当します。プログラム内の特定の文字の値が 20,002 文字を超える場合、VARCHAR2 は要件を満たすことができません。現時点では 2 つのオプションがあります。1 つは複数の VARCHAR2 を使用してそれを表す方法で、もう 1 つは LOB フィールドを使用する方法です。ここでは 2 番目の方法を見ていきます。
まず、Oracle の LOB フィールドの概要を見てみましょう。 Oracle の LOB タイプは、BLOB、CLOB、BFILE の 3 つのタイプに分類されます。 CLOB は文字 LOB と呼ばれ、BLOB および BFILE はバイナリ データを格納するために使用されます。 CLOB と BLOB の最大長は 4GB で、Oracle データベースに値を保存します。 BFILE は BLOB に似ていますが、データを外部ファイルに配置するため、外部 BLOB (外部 BLOB) とも呼ばれます。
MYSQL については誰もがよく知っていると思います。 MYSQL には、TEXT や BLOB などの同様のデータ型があります。 PHP の MYSQL 関数では、他のタイプのデータと同様に、TEXT/BLOB に対する操作は直接的です。しかし、Oracle では状況が異なります。 Oracle は LOB を特別なデータ型として扱うため、操作に従来の方法を使用できません。たとえば、INSERT ステートメントで LOB フィールドに値を直接挿入したり、LIKE を使用して検索したりすることはできません。
ここでは、PHP の OCI 関数を使用して LOB データを挿入、取得、クエリする方法を示すいくつかの例を示します。
挿入では、
INSERT ステートメントを直接使用して LOB フィールドに値を挿入することはできません。一般に、次の手順があります。
1. まず INSERT 文を分析し、LOB 記述子を返します。
2. OCI 関数を使用してローカル LOB オブジェクトを生成します
。 3. LOB オブジェクトを LOB 記述子にバインドします
。 4. INSERT 文を実行します
。 5. 割り当てLOB オブジェクトへの値
6. LOB オブジェクトと SQL ステートメント ハンドルを解放します。
次の例では、ユーザーがアップロードしたイメージ ファイルを BLOB (または BFILE、操作は若干異なります) に格納します。まず、次の構造を持つテーブルを作成します。
CREATE TABLE PICTURES (
ID番号、
説明 VARCHAR2(100)、
MIME VARCHAR2(128)、
画像ブロブ
);
ID の自動増加を実現したい場合は、別の SEQUENCE:
CREATE SEQUENCE PIC_SEQ
を作成してから、データの処理に使用される PHP プログラム コードを作成します。
<?php
//Oracle データベース接続を確立します
$conn = OCILogon($user, $password, $SID)
//SQL ステートメントを Oracle に送信します。
//ここで注意すべき 2 つの点: まず、EMPTY_BLOB() 関数を使用します。これは、LOB ロケータを返す Oracle の内部関数です。 LOB を挿入する場合、このメソッドを使用できるのは、最初に空の LOB ロケーターを生成し、次にこのロケーターを操作する場合のみです。 EMPTY_BLOB() 関数は BLOB タイプ用であり、CLOB に対応する関数は EMPTY_CLOB() です。 2 番目は RETURNING 以降の部分で、PHP の OCI 関数が処理できるように画像を返します。
$stmt = OCIParse($conn,"ピクチャへの挿入 (ID、説明、ピクチャ)
VALUES (pic_seq.NEXTVAL, '$description', '$lob_upload_type', EMPTY_BLOB()) RETURNING picture INTO :PICTURE");
//ローカル LOB オブジェクトの記述子を生成します。関数の 2 番目のパラメータ OCI_D_LOB に注意してください。 LOB オブジェクトを生成することを意味します。その他の可能性としては、BFILE オブジェクトと ROWID オブジェクトに対応する OCI_D_FILE および OCI_D_ROWID があり
ます
。
OCIBindByName
($stmt, ':PICTURE', &$lob, -1, OCI_B_BLOB);
OCIExecute($stmt);
// データを LOB オブジェクトに保存します。ここでのソース データはファイルであるため、LOB オブジェクトの savefile() メソッドを直接使用します。 LOB オブジェクトのその他のメソッドには、save() および load() があり、それぞれデータの保存と取得に使用されます。ただし、BFILE タイプにはメソッドが 1 つだけあり、それが save()
if($lob->savefile($lob_upload)){
OCICommit($conn);
echo "アップロード成功<br>";
}それ以外{
echo "アップロードに失敗しました<br>";
}
// LOB オブジェクトを解放します
OCIFreeDesc($lob);
OCIFreeStatement($stmt);
OCILogoff($conn);
?>
もう 1 つ注意すべき点があります。LOB フィールドの値は少なくとも 1 文字である必要があるため、save() または savefile() の前に値を空にできないことを確認してください。そうしないと、Oracle でエラーが発生します。
LOB からデータを
取得する
には 2 つの方法があります。1 つは LOB オブジェクトを生成し、それを SELECT ステートメントによって返されたロケーターにバインドし、LOB オブジェクトのload() メソッドを使用してデータを取得する方法で、もう 1 つは PHP の OCIFetch*** 関数を直接使用する方法です。最初の方法は 2 番目の方法よりもはるかに面倒なので、2 番目の方法については直接説明します。
上記の表は引き続き使用します。
<?php
$conn = OCILogon($user, $password, $SID);
$stmt = OCIParse($conn,"SELECT * FROM PICTURES WHERE ID=$pictureid");
OCIExecute($stmt);
//秘密は PCIFetchInfo の 3 番目のパラメータ OCI_RETURN_LOBS にあります。 3番目のパラメータはFETCHモードです。 OCI_RETURN_LOBSの場合、LOB値はLOBロケータではなく結果配列に直接入れられるため、LOBオブジェクトのload()メソッドは必要ありません。
if (OCIFetchInto($stmt, $result, OCI_ASSOC+OCI_RETURN_LOBS))
{
echo "コンテンツタイプ: " . StripSlashes($result[MIME]);
echo StripSlashes($result[PICTURE]);
}
OCIFreeStatement($stmt);
OCILogoff($conn);
?>
このプログラムはLOBに配置されたデータ(ピクチャ)を表示するために使用します。メソッドの呼び出し (スクリプト名が getpicture.php であると仮定):
<IMG SRC="getpicture.php?pictureid=99" ALT="Oracle LOB に配置されたピクチャ">
クエリは
前に説明しましたが、Oracle の LOB フィールドは次のとおりです。 LIKE はマッチングに使用できません。何をするか?実際、Oracle には DBMS_LOB と呼ばれる匿名パッケージがあり、これには LOB の操作に必要なすべてのプロセスが含まれています。
次のようなテーブルがあるとします。
CREATE TABLE ARTICLES (
ID番号、
TITLE VARCHAR2(100)、
コンテンツ CLOB
);
記事のコンテンツは CONTENT フィールドに配置されます。
ここで、コンテンツに「PHP 中国語ユーザー」を含むすべての記事を検索したいと思います。これは次のように実行できます
。
$conn = OCILogon($user, $password, $SID);
// DBMS_LOB.INSTR プロシージャは WHERE 句で使用されます。これには 4 つのパラメーターがあり、最初の 2 つは LOB ロケーター (フィールドによって直接表すことができます) を表し、後の 2 つは開始オフセットと出現数を表します。戻り値は 0 より大きいかどうかを判断する必要があることに注意してください。
$stmt = OCIParse($conn,"SELECT * FROM ARTICLES WHERE DBMS_LOB.INSTR(CONTENT, 'PHP Chinese User', 1, 1) > 0");
OCIExecute($stmt);
if (OCIFetchInto($stmt, $result, OCI_ASSOC+OCI_RETURN_LOBS))
{
...
}
OCIFreeStatement($stmt);
OCILogoff($conn);
?>
Oracle では、LENGTH、SUBSTR などの LOB データを操作するためのプロシージャも多数提供しています。詳細な使用方法については、Oracle の開発マニュアルを参照してください。
OracleデータベースのLOB型データに対する操作は以上です。私は長い間オラクルと連絡を取っていなかったので、この記事には間違いがあるかもしれません。どなたでも私を批判したり修正したりしてください。