SET status=$SYSTEM.SQL.Util.SetOption("AutoCommit",intval,.oldval)
以下の intval 整数オプションを使用できます。
-
1 または IMPLICIT (自動コミットがオン — 既定) — INSERT ごとに個別のトランザクションが構成されます。
-
2 または EXPLICIT (自動コミットがオフ) — 進行中のトランザクションがない場合は、INSERT コマンドによってトランザクションは自動的に開始されます。ただし、COMMIT または ROLLBACK で明示的にトランザクションを終了する必要があります。EXPLICIT モードでは、トランザクションあたりのデータベース操作の数は、ユーザ定義です。
-
0 または NONE (自動トランザクションなし) — INSERT を呼び出してもトランザクションは開始されません。INSERT 操作の失敗により、行の一部が挿入されたり挿入されなかったりすることで、データベースが整合性のない状態になる可能性があります。このモードでトランザクションのサポートを提供するには、START TRANSACTION を使用してトランザクションを開始し、COMMIT または ROLLBACK を使用してトランザクションを終了する必要があります。
シャード・テーブルは常に、自動トランザクションなしのモードに設定されます。つまり、シャード・テーブルに対する挿入、更新、および削除はすべて、トランザクションの範囲外で実行されます。
現在のプロセスのアトミック性設定を確認するには、以下の ObjectScript の例のように、GetOption("AutoCommit")Opens in a new tab メソッドを使用します。
SET stat=$SYSTEM.SQL.Util.SetOption("AutoCommit",$RANDOM(3),.oldval)
IF stat'=1 {WRITE "SetOption failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET x=$SYSTEM.SQL.Util.GetOption("AutoCommit")
IF x=1 {
WRITE "Default atomicity behavior",!
WRITE "automatic commit or rollback" }
ELSEIF x=0 {
WRITE "No transaction initiated, no atomicity:",!
WRITE "failed DELETE can leave database inconsistent",!
WRITE "rollback is not supported" }
ELSE { WRITE "Explicit commit or rollback required" }
トランザクションのロックしきい値の変更
%NOLOCK キーワードを指定しない場合、INSERT、UPDATE、および DELETE 操作時に自動的にレコードに標準のロックがかかります。影響を受ける各レコード (行) は、現在のトランザクションが継続している間はロックされます。
既定のロックしきい値は、テーブルごとに 1000 ロックです。トランザクションの間にテーブルから 1000 件を超えるレコードを挿入すると、ロックのしきい値に到達し、InterSystems IRIS は自動的にロック・レベルをレコード・ロックからテーブル・ロックに上げます。これによってトランザクション時に、ロック・テーブルをオーバーフローすることなく、大規模な挿入を実行できます。
InterSystems IRIS は、以下のロック・エスカレーション策のいずれかを適用します。
-
"E" タイプのロック・エスカレーション — InterSystems IRIS は、以下が当てはまる場合にこのロック・エスカレーションを使用します。
-
テーブルのクラスで %Storage.Persistent を使用している。これは、管理ポータルの SQL スキーマ表示の [カタログの詳細] から確認できます。
-
クラスで、IDKey インデックスが指定されていないか、単一プロパティの IDKey インデックスが指定されている。
"E" タイプのロック・エスカレーションの詳細は、"LOCK" を参照してください。
-
従来の SQL ロック・エスカレーション — このロック・エスカレーションは、クラスにマルチプロパティの IDKey インデックスがある場合に発生する可能性があります。この場合は、%Save ごとにロック・カウンタがインクリメントされます。つまり、トランザクション内の単一オブジェクトを 1001 回保存すると、InterSystems IRIS はロックのエスカレーションを試みます。
どちらのロック・エスカレーション策の場合も、$SYSTEM.SQL.Util.GetOption("LockThreshold")Opens in a new tab メソッドを使用して、現在のシステム全体用ロックしきい値を決定できます。既定値は 1000 です。以下のオプションのいずれかを使用してシステム全体のロックしきい値を構成できます。
ロックしきい値を変更するには、%Admin リソース管理に対する USE 許可を持っている必要があります。InterSystems IRIS は、ロックしきい値の変更を現在のプロセスすべてに即座に適用します。
結果として、自動ロック・エスカレーションでは、デッドロックの状況が起こる可能性があります。つまり、テーブル・ロックへのエスカレーションを試みたときに、テーブル内のレコード・ロックを保持する別プロセスとの競合が起こる可能性があります。これを回避するには、いくつかの方法が考えられます。
-
ロック・エスカレーションがトランザクション内で起こる可能性が低くなるように、ロック・エスカレーションのしきい値を上げる。
-
ロック・エスカレーションが即座に起こるように、ロック・エスカレーションのしきい値を大幅に下げる。これにより、別プロセスが同一テーブル内のレコードをロックする機会が少なくなります。
-
トランザクションが継続している間はテーブル・ロックを適用し、レコード・ロックは実行しない。これは、LOCK TABLE、UNLOCK TABLE (テーブル・ロックがトランザクションの終了まで持続するよう、IMMEDIATE キーワードはなし) の順に指定することで、トランザクション開始時に実行できます。その後、%NOLOCK オプションを使用して挿入を実行します。
自動ロック・エスカレーションは、ロック・テーブルのオーバーフローを防ぐことを目的としています。ただし、大量の挿入などを実行したために <LOCKTABLEFULL> エラーが発生した場合は、INSERT によって SQLCODE -110 エラーが発行されます。
トランザクションでのロックの詳細は、"トランザクション処理" を参照してください。
子テーブルの挿入
子テーブルへの INSERT 操作時には、親テーブル内の対応する行に共有ロックがかかります。この行は、子テーブル行の挿入中はロックされます。その後、ロックは解除されます (トランザクションの終了までロック状態が継続することはありません)。これにより、参照される親の行がこの挿入操作の間に変更されることがなくなります。
詳細
重複テーブルにデータをコピーする
列の順序が一致し、互換性のあるデータ型であれば、SELECT * と組み合わせて INSERT を使用し、あるテーブルから重複テーブルへデータをコピーできます。この操作を使用して、既存のデータを再定義されたテーブルにコピーし、元のテーブルでは有効にならなかったであろう将来の列データ値がこのテーブルで受け入れられます。以下にサンプル構文を示します。
INSERT INTO Sample.DupTable SELECT * FROM Sample.SrcTable
列名が一致する必要はありませんが、コピー元のテーブルとコピー先のテーブルのデータは以下の要件を満たす必要があります。
-
コピー元テーブルの値のデータ型は、コピー先テーブルの列のデータ型と互換性がある必要があります。例えば、INTEGER 値は VARCHAR に変換できるため、INTEGER 列の整数データを VARCHAR 列に挿入することは可能です。データ値に互換性がない場合、INSERT は SQLCODE -104 エラーで失敗します。挿入するデータを挿入先のデータ型に明示的に変換するには、CONVERT 関数を使用します。
-
コピー元テーブルの値のデータ型の長さは、コピー先テーブルの列の長さと適合する必要があります。定義されている列データの長さが相互に一致する必要はありません。実際のデータと一致する必要があるだけです。例えば、SrcTable は FullName VARCHAR(60) 列を持ち、DupTable は対応する PersonName VARCHAR(40) 列を持つとします。40 文字を超える既存の FullName がない場合、INSERT は成功します。いずれかの FullName が 40 文字を超える場合、INSERT は SQLCODE -104 エラーで失敗します。
-
2 つのテーブルの列順には互換性がある必要があり、互換性がない場合、INSERT コマンドは SQLCODE -64 エラーで失敗します。DDL CREATE TABLE は、定義された順序で列をリストします。テーブルを定義する永続クラスはアルファベット順に列をリストします。
-
テーブルには互換性のある列数が必要ですが、コピー先テーブルにはコピーされた列以外の列を含めることができます。例えば、SrcTable は、列 FullName VARCHAR(60) および Age INTEGER を持つことができ、DupTable は PersonName VARCHAR(60)、Years INTEGER、および ShoeSize INTEGER を持つことができます。
-
コピー元テーブルとコピー先テーブルのいずれかでパブリック RowID が定義されている場合、データのコピーは以下の表に示すように制限されます。
コピー元テーブル |
コピー先テーブル |
コピー操作の動作 |
プライベート RowID |
プライベート RowID |
INSERT SELECT を SELECT * と共に使用して、データを重複テーブルにコピーできます。 |
パブリック RowID |
パブリック RowID |
INSERT SELECT を使用して、データを重複テーブルにコピーすることはできません。SQLCODE -111 エラーが生成されます。 |
プライベート RowID |
パブリック RowID |
INSERT SELECT を使用して、データを重複テーブルにコピーすることはできません。SQLCODE -111 エラーが生成されます。 |
パブリック RowID |
プライベート RowID |
INSERT SELECT を SELECT * と共に使用して、データを重複テーブルにコピーすることはできません。一方の選択リストに RowID が存在していて選択リストが非互換になるため、SQLCODE -64 エラーが生成されます。INSERT SELECT をすべての列名のリスト (RowID は含まない) と共に使用して、重複テーブルにデータをコピーできます。ただし、コピー元に外部キーのパブリック RowID がある場合、外部キー・リレーションシップはコピー先テーブルでは保持されません。コピー先は新しいシステム生成 RowID を受け取ります。
コピー元テーブルに外部キーのパブリック RowID があり、コピー先テーブルに同じ外部キー・リレーションシップを設定したい場合は、CREATE TABLE で %CLASSPARAMETER ALLOWIDENTITYINSERT=1 を使用してコピー先テーブルを定義する必要があります。テーブルが ALLOWIDENTITYINSERT=1 として定義されている場合、この設定を SetOption("IdentityInsert")Opens in a new tab メソッドで変更することはできません。 |
DDL CREATE TABLE は既定で RowID をプライベートとして定義します。テーブルを定義する永続クラスは、既定で RowID をパブリックとして定義します。これをプライベートにするには、永続クラスを定義する際に、SqlRowIdPrivate クラス・キーワードを指定する必要があります。ただし、外部キーで参照できるのはパブリック RowID を持つテーブルだけです。
コピー元またはコピー先のテーブルの永続クラスで Final キーワードが定義されている場合、このキーワードは重複テーブルへのデータのコピーに影響を与えません。
%SerialObject プロパティにデータを挿入する
%SerialObject にデータを挿入する際は、埋め込み %SerialObject を参照するテーブル (永続クラス) に挿入する必要があります。%SerialObject に直接挿入することはできません。例えば、永続クラスにプロパティ Paddress があり、これはプロパティ Street、City、Country がこの順番に含まれるシリアル・オブジェクトを参照するものとします。このプロパティの値を挿入する方法は以下のとおりです。
-
参照するフィールドを使用して、複数の %SerialObject プロパティの値を %List 構造として挿入する。以下に例を示します。
INSERT INTO MyTable SET PAddress=$LISTBUILD('123 Main St.','Newtown','USA')
INSERT INTO MyTable (PAddress) VALUES ($LISTBUILD('123 Main St.','Newtown','USA'))
%List には、シリアル・オブジェクト (またはプレースホルダとしてのコンマ) のプロパティの値が、このシリアル・オブジェクトで指定されている順序で含まれる必要があります。
このタイプの挿入では、%SerialObject プロパティ値の検証は実行されない場合があります。したがって、%List 構造を使用して %SerialObject プロパティを挿入したら、$SYSTEM.SQL.Schema.ValidateTable() メソッドを使用してテーブル・データの検証を実行してください。
-
アンダースコア構文を使用して、個々の %SerialObject プロパティの値を任意の順序で挿入する。以下に例を示します。
INSERT INTO MyTable SET PAddress_City='Newtown',PAddress_Street='123 Main St.',PAddress_Country='USA'
指定されていないシリアル・オブジェクト・プロパティは、既定の NULL になります。
このタイプの挿入では、%SerialObject プロパティ値の検証が実行されます。
関連項目