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 のいくつかの例を使用して Oracle LOB データを管理し、PHP の OCI 関数を使用して LOB データを挿入、取得、クエリする方法を説明します。
Insert
INSERT ステートメントを直接使用して LOB フィールドに値を挿入することはできません。通常の状況では、次の手順があります:
1. まず INSERT ステートメントを分析し、LOB 記述子を返します
2. OCI 関数を使用してローカル LOB オブジェクトを生成します
3. LOB オブジェクトを LOB On にバインドします。記述子
4. INSERT ステートメントを実行します
5. LOB オブジェクトに値を割り当てます
6. LOB オブジェクトと SQL ステートメントのハンドルを解放します
次の例は、Oracle LOB データを保存する例です。ユーザーによって BLOB (または BFILE、操作は若干異なります) にアップロードされます。まず、次の構造のテーブルを作成します:
<ol class="dp-xml"> <li class="alt"><span><span>CREATE TABLE PICTURES ( </span></span></li> <li><span>ID NUMBER, </span></li> <li class="alt"><span>DESCRIPTION VARCHAR2(100), </span></li> <li><span>MIME VARCHAR2(128), </span></li> <li class="alt"><span>PICTURE BLOB </span></li> <li><span>); </span></li> </ol>
IDの自動増加を実現したい場合は、SEQUENCE:
CREATE SEQUENCE PIC_SEQ;
を作成します。次に、処理に使用されるPHPプログラムコードがあります。データ。
<ol class="dp-xml"> <li class="alt"><span><span>< ?php </span></span></li> <li><span>//建立Oracle数据库连接 </span></li> <li class="alt"> <span>$</span><span class="attribute">conn</span><span> = </span><span class="attribute-value">OCILogon</span><span>($user, $password, $SID); </span> </li> <li><span>//提交SQL语句给Oracle </span></li> <li class="alt"><span>//在这里要注意的两点:一是用EMPTY_BLOB()函数。这是Oracle的内部函数,<br>返回一个LOB的定位符。在插入LOB时,只能用这个办法先 生成一个空的LOB定<br>位符,然后对这个定位符进行操作。EMPTY_BLOB()函数是针对BLOB类型的,<br>对应于CLOB的是 EMPTY_CLOB()。二是RETURNING后面的部分,把picture<br>返回,让PHP的OCI函数能够处理。 </span></li> <li> <span>$</span><span class="attribute">stmt</span><span> = </span><span class="attribute-value">OCIParse</span><span>($conn,”INSERT INTO PICTURES (id, description, picture) </span> </li> <li class="alt"><span>VALUES (pic_seq.NEXTVAL, ‘$description’, ‘$lob_upload_type’<br>, EMPTY_BLOB()) RETURNING picture INTO ICTURE”); </span></li> <li><span>//生成一个本地LOB对象的描述符。注意函数的第二个参数:OCI_D_LOB,<br>表示生成一个LOB对象。其它可能的还有OCI_D_FILE和OCI_D_ROWID,<br>分别对应于BFILE和ROWID对象。 </span></li> <li class="alt"> <span>$</span><span class="attribute">lob</span><span> = </span><span class="attribute-value">OCINewDescriptor</span><span>($conn, OCI_D_LOB); </span> </li> <li><span>//将生成的LOB对象绑定到前面SQL语句返回的定位符上。 </span></li> <li class="alt"><span>OCIBindByName($stmt, ‘:PICTURE’, &$lob, -1, OCI_B_BLOB); </span></li> <li><span>OCIExecute($stmt); </span></li> <li class="alt"><span>//向LOB对象中存入数据。因为这里的源数据是一个文件,所以直接用LOB<br>对象的savefile()方法。LOB对象的其它方法还有:save()和load(),<br>分别用来保存和取出数据。但BFILE类型只有一个方法就是save() </span></li> <li><span>if($lob->savefile($lob_upload)){ </span></li> <li class="alt"><span>OCICommit($conn); </span></li> <li><span>echo “上传成功< br>”; </span></li> <li class="alt"><span>}else{ </span></li> <li><span>echo “上传失败< br>”; </span></li> <li class="alt"><span>} </span></li> <li><span>//释放LOB对象 </span></li> <li class="alt"><span>OCIFreeDesc($lob); </span></li> <li><span>OCIFreeStatement($stmt); </span></li> <li class="alt"><span>OCILogoff($conn); </span></li> <li><span>?> </span></li> </ol>
もう 1 つの注意事項: LOB フィールドの値は少なくとも 1 文字である必要があるため、save() または savefile() の前に、値が空であってはいけないことを確認してください。そうしないと、Oracle でエラーが発生します。
取得
PHP は Oracle LOB データを管理します。LOB からデータを取得するには 2 つの方法があります。 1 つは LOB オブジェクトを生成し、それを SELECT ステートメントによって返されたロケーターにバインドし、LOB オブジェクトのload() メソッドを使用してデータを取得する方法で、もう 1 つは PHP の OCIFetch*** 関数を直接使用する方法です。最初の方法は 2 番目の方法よりもはるかに面倒なので、2 番目の方法については直接説明します。
上の表は引き続き使用します。
<ol class="dp-xml"> <li class="alt"><span><span>< ?php </span></span></li> <li> <span>$</span><span class="attribute">conn</span><span> = </span><span class="attribute-value">OCILogon</span><span>($user, $password, $SID); </span> </li> <li class="alt"> <span>$</span><span class="attribute">stmt</span><span> = </span><span class="attribute-value">OCIParse</span><span>($conn,”SELECT * <br>FROM PICTURES WHERE </span><span class="attribute">ID</span><span>=$pictureid”); </span> </li> <li><span>OCIExecute($stmt); </span></li> <li class="alt"><span>//秘密就在PCIFetchInfo的第三个参数上:<br>OCI_RETURN_LOBS。第三个参数是FETCH的模式,<br>如果OCI_RETURN_LOBS,就直接把LOB的值放到结<br>果数组中,而不是LOB定位符,也就不用LOB对象的load()方法了。 </span></li> <li><span>if (OCIFetchInto($stmt, $result, OCI_ASSOC+OCI_RETURN_LOBS)) </span></li> <li class="alt"><span>{ </span></li> <li><span>echo “Content-type: ” . StripSlashes($result[MIME]); </span></li> <li class="alt"><span>echo StripSlashes($result[PICTURE]); </span></li> <li><span>} </span></li> <li class="alt"><span>OCIFreeStatement($stmt); </span></li> <li><span>OCILogoff($conn); </span></li> <li class="alt"><span>?> </span></li> </ol>
このプログラムはLOBに配置されたデータ(画像)を表示するために使用されます。メソッドの呼び出し (スクリプト名が getpicture.php であると仮定):
<ol class="dp-xml"><li class="alt"><span><span>< IMG </span><span class="attribute">SRC</span><span>=”getpicture.php?</span><span class="attribute">pictureid</span><span>=</span><span class="attribute-value">99</span><span>″ <br></span><span class="attribute">ALT</span><span>=”放在Oracle LOB中的图片”> </span></span></li></ol>
Query
前述したように、PHP は Oracle LOB データを管理し、LIKE を使用して Oracle の LOB フィールドと一致させることはできません。どうやってするの?実際、Oracle には DBMS_LOB と呼ばれる匿名パッケージがあり、これには LOB の操作に必要なすべてのプロセスが含まれています。
次のようなテーブルがあるとします。
<ol class="dp-xml"> <li class="alt"><span><span>CREATE TABLE ARTICLES ( </span></span></li> <li><span>ID NUMBER, </span></li> <li class="alt"><span>TITLE VARCHAR2(100), </span></li> <li><span>CONTENT CLOB </span></li> <li class="alt"><span>); </span></li> </ol>
記事のコンテンツは CONTENT フィールドに配置されます。
次に、コンテンツに「PHP 中国語ユーザー」を含むすべての記事を検索する必要があります。次のように実行できます。
<ol class="dp-xml"> <li class="alt"><span><span>< ?php </span></span></li> <li> <span>$</span><span class="attribute">conn</span><span> = </span><span class="attribute-value">OCILogon</span><span>($user, $password, $SID); </span> </li> <li class="alt"><span>//WHERE子句中用了DBMS_LOB.INSTR过程。它有四个参数,<br>前面两个分别表示LOB的定位符(可以直接用字段表示)<br>和要查找的字符串;后面两个分别表示开始的偏移量和出现的次数。<br>要注意的是必须判断它的返回值,也就是要大于0。 </span></li> <li> <span>$</span><span class="attribute">stmt</span><span> = </span><span class="attribute-value">OCIParse</span><span>($conn,”SELECT * FROM ARTICLES <br>WHERE DBMS_LOB.INSTR(CONTENT, ‘PHP中文用户’, 1, 1) > 0″); </span> </li> <li class="alt"><span>OCIExecute($stmt); </span></li> <li><span>if (OCIFetchInto($stmt, $result, OCI_ASSOC+OCI_RETURN_LOBS)) </span></li> <li class="alt"><span>{ </span></li> <li><span>… </span></li> <li class="alt"><span>} </span></li> <li><span>OCIFreeStatement($stmt); </span></li> <li class="alt"><span>OCILogoff($conn); </span></li> <li><span>?> </span></li> </ol><br>
Oracle では、LENGTH、SUBSTR などの LOB データを操作するための多くのプロシージャも提供しています。詳細な使用方法については、Oracle の開発マニュアルを参照してください。
Oracle LOB データを管理するための PHP の操作については以上です。私は長い間オラクルと連絡を取っていなかったので、この記事には間違いがあるかもしれません。どなたでも私を批判したり修正したりしてください。