ストリーム・データ (BLOB と CLOB) の格納と使用
Caché SQL には、データベースに BLOB (Binary Large Objects) や CLOB (Character Large Objects) を保存する機能があります。以下の項目について説明します。
ストリーム・フィールドと SQL
Caché SQL はストリーム・フィールドをサポートしています。この型のフィールドは、大容量のテキスト、イメージ、ビデオ、音声などのデータに使用します。以下の SQL 演算はストリーム・フィールドをサポートしています。
-
SELECT は、以下の例に示すように、ストリーム・フィールドを選択し、ストリーム・オブジェクトの整形式 OID (オブジェクト ID) 値を返します。
SELECT Name,Picture,Notes FROM Sample.Employee WHERE Picture IS NOT NULL
-
IS [NOT] NULL、%CONTAINS、および %CONTAINSTERM 述語は、ストリーム・フィールドのデータ値に適用可能です。
BETWEEN、EXISTS、IN、%INLIST、LIKE、%MATCHES、および %PATTERN 述語は、以下の例に示すようにストリーム・オブジェクトの OID 値に適用可能です。
SELECT Name,Notes FROM Sample.Employee WHERE Notes %MATCHES '*1[0-9]*GlobalChar*'
ストリーム・フィールドでその他の述語条件を使用しようとすると、SQLCODE -313 エラーが返されます。
-
SELECT では、COUNT、%OBJECT、CHARACTER_LENGTH (または CHAR_LENGTH または DATALENGTH)、SUBSTRING、CONVERT、%SIMILARITY、XMLCONCAT、XMLELEMENT、XMLFOREST、および %INTERNAL 関数以外には、ストリーム値フィールドに関数を適用できません。ストリーム・フィールドをその他の SQL 関数で引数として使用しようとすると、SQLCODE -37 エラーが返されます。
-
COUNT 集約関数は、以下の例に示すように、ストリーム・フィールドを取得し、フィールドに NULL でない値を含む行をカウントします。
SELECT COUNT(Picture) AS PicRows,COUNT(Notes) AS NoteRows FROM Sample.Employee
ただし、COUNT(DISTINCT) はストリーム・フィールドではサポートされません。
-
%OBJECT 関数は、以下の例に示すように、ストリーム・オブジェクトを開き (OID を取得し)、oref (オブジェクト参照) を返します。
SELECT Name,Notes,%OBJECT(Notes) AS NotesOref FROM Sample.Employee WHERE Notes IS NOT NULL
-
CHARACTER_LENGTH 関数、CHAR_LENGTH 関数、および DATALENGTH 関数は、以下の例に示すように、ストリーム・フィールドまたは、ストリーム・フィールドの oref (%OBJECT(streamfield)) を取得します。
SELECT Name,DATALENGTH(Notes) AS NotesNumChars FROM Sample.Employee WHERE Notes IS NOT NULL
-
SUBSTRING 関数は、以下の例に示すように、ストリーム・フィールドまたはストリーム・フィールドの oref (%OBJECT(streamfield)) を取得し、ストリーム・フィールドの指定された部分文字列を返します。
SELECT Name,SUBSTRING(Notes,1,10) AS Notes1st10Chars FROM Sample.Employee WHERE Notes IS NOT NULL
-
CONVERT 関数を使用して、以下の例に示すように、ストリーム・データ型を VARCHAR に変換できます。
SELECT Name,CONVERT(VARCHAR(100),Notes) AS NotesText FROM Sample.Employee WHERE Notes IS NOT NULL
CONVERT(datatype,expression) 構文はストリーム・データ変換をサポートします。{fn CONVERT(expression,datatype)} 構文はストリーム・データ変換をサポートしません。
-
%INTERNAL 関数は、ストリーム・フィールドに使用できますが、演算を実行しません。
-
-
INSERT と UPDATE は、ストリーム・オブジェクトの整形式 OID (オブジェクト ID) 値をストリーム・フィールドの新しい値として受け入れます。レコードにストリーム・フィールドが含まれている場合、INSERT 演算または UPDATE 演算では、複数行ではなく単一行のみを変更できます。INSERT でストリーム・フィールドの規定値を挿入できます。
-
ストリーム・フィールドにインデックスを付けることはできません。
BLOB と CLOB
Caché SQL には、データベースに BLOB (Binary Large Objects) や CLOB (Character Large Objects) を保存する機能があります。BLOB は、イメージなどのバイナリ情報の保存に、CLOB は文字情報の保存に使用します。BLOB と CLOB は、最大 4 ギガバイトのデータを保存できます (この制限は JDBC と ODBC の仕様により決められています)。
BLOB と CLOB の処理方法はほぼ同じですが、ODBC または JDBC クライアントからアクセスされたときに、文字エンコード変換を処理する方法 (Unicode からマルチバイト文字への変換など) のみ異なります。BLOB のデータはバイナリ・データとして処理され、他の文字コードに変換されませんが、CLOB のデータは文字データとして処理され、必要に応じて変換されます。
BLOB と CLOB には、以下の制限事項があります。
-
BLOB または CLOB のフィールドには、インデックスを定義できません。
-
WHERE 節の中では、いくつかの特定の例外を除き、BLOB フィールドも CLOB フィールドも使用できません。詳細は、"Caché SQL リファレンス" の "WHERE 節" を参照してください。
-
BLOB や CLOB を含む複数の行は、UPDATE も INSERT もできません。1 行ずつ操作する必要があります。
同じ制限がストリーム・フィールドに適用されます。オブジェクトの観点から見ると、BLOB と CLOB は ストリーム・オブジェクトと見なされます。詳細は、"Caché オブジェクトの使用法" の “ストリームを使用した作業” の章を参照してください。
DDL を使用したストリーム・フィールドの定義
DDL 内では、CLOB フィールドは、LONG VARCHAR SQL データ型を使用して定義されます。BLOB フィールドは、LONG VARBINARY SQL データ型を使用して定義されます。
CREATE TABLE MyApp.Person (
Name VARCHAR(50) not null,
Notes LONGVARCHAR,
Photo LONGVARBINARY
)
ストリーム・データ型のデータ型マッピングについては、"Caché SQL リファレンス" の "データ型" リファレンス・ページを参照してください。
空の BLOB
バイナリ・ストリーム・ファイル (BLOB) に 1 つの出力不能文字 $CHAR(0) が含まれる場合、これは空のバイナリ・ストリームと見なされます。これは、空のバイナリ・ストリーム値 "" と同じです。存在はしていますが (NULL ではありませんが)、その長さは 0 です。
ストリーム・フィールドの同時処理ロック
Caché は、ストリーム・データに対するロックを取得することで、別のプロセスによる同時操作からストリーム・データの値を保護します。
Caché は、書き込み操作を実行する前に、排他ロックを取得します。この排他ロックは、書き込み操作の完了直後に解放されます。
Caché は、最初の読み取りが行われるときに共有ロックを取得します。共有ロックは、ストリームが実際に読み取られるときにのみ取得され、ストリーム全体がディスクから内部の一時入力バッファに読み込まれた直後に解放されます。
Caché メソッドでのストリーム・フィールドの使用
Caché メソッド内で、埋め込み SQL またはダイナミック SQL を使用して、直接的に BLOB 値または CLOB 値を使用することはできません。その代わり、SQL を使用して BLOB または CLOB のストリーム識別子を見つけてから、%AbstractStreamOpens in a new tab オブジェクトのインスタンスを作成してデータにアクセスします。
例えば、ダイナミック SQL によって以下の Basic メソッドのストリームを読むことができます。
/// Display the memos for all Persons with a given city
/// within an HTML table
ClassMethod DisplayMemo(city As %String = "") [language = basic]
{
' Define a query to find all the Stream Id values for memo
tStatement = New %SQL.Statement()
tStatus = tStatement.%Prepare("SELECT Name,Memo FROM MyApp.Person WHERE Home_City = ?")
rset = tStatement.%Execute(city)
' iterate over the results
PrintLn "<TABLE>"
While (rset.%Next())
PrintLn "<TR>"
' display the person's name
PrintLn "<TD>" & rset.Name & "</TD>"
' Now open the stream object containing the memo
stream = OpenId %Stream(rset.Memo)
Print "<TD>"
' Write the contents of the stream to the current device
stream.OutputToDevice()
PrintLn "</TD></TR>"
Wend
PrintLn "</TABLE>"
}
ODBC からのストリーム・フィールドの使用
ODBC の規格では、BLOB と CLOB フィールドの認識や特別な処理方法などは、提供されていません。Caché SQL は、ODBC 内の CLOB フィールド (LONG VARCHAR タイプ) を表しています。BLOB フィールドは、LONG VAR BINARY タイプとして表されます。ストリーム・データ型のデータ型マッピングについては、"Caché SQL リファレンス" の "データ型" リファレンス・ページを参照してください。
ODBC ドライバおよびサーバは、特別なプロトコルを使用して、BLOB や CLOB フィールドへアクセスします。通常、CLOB や BLOB フィールドを使用するには、ODBC アプリケーションに特別なコードを書く必要があります。一般的に、標準のレポート・ツールはこれらをサポートしていません。
JDBC からのストリーム・フィールドの使用
Java プログラムで、標準 JDBC BLOB/CLOB インタフェースを使用して、BLOB や CLOB からデータの検索や設定を実行できます。以下はその例です。
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT MyCLOB,MyBLOB FROM MyTable");
rs.next(); // fetch the Blob/Clob
java.sql.Clob clob = rs.getClob(1);
java.sql.Blob blob = rs.getBlob(2);
// Length
System.out.println("Clob length = " + clob.length());
System.out.println("Blob length = " + blob.length());
// ...
BLOB または CLOB の使用を終了したら、free() メソッドを明示的に呼び出して Java のオブジェクトを閉じ、サーバにメッセージを送信してストリーム・リソース (オブジェクトとロック) を解放する必要があります。Java オブジェクトを範囲外にするだけでは、サーバ・リソースをクリーンアップするためのメッセージは送信されません。