Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

UPDATE (SQL)

指定されたテーブルの指定された列に新しい値を設定します。

Synopsis

UPDATE [%keyword] table-ref [[AS] t-alias]    value-assignment-statement     [FROM [optimize-option] select-table [[AS] t-alias]          {, select-table2 [[AS] t-alias]} ]    [WHERE condition-expression]  UPDATE [%keyword] table-ref [[AS] t-alias]    value-assignment-statement    [WHERE CURRENT OF cursor]  value-assignment-statement ::=    SET column1 = scalar-expression1 {,column2 = scalar-expression2} ...  |    [ (column1 {,column2} ...) ] VALUES (scalar-expression1 {,scalar-expression2} ...)  |    VALUES :array()

引数

%keyword オプション — %NOCHECK、%NOFPLAN、%NOINDEX、%NOJOURN、%NOLOCK、%NOTRIGGER、%PROFILE、%PROFILE_ALL のキーワード・オプションのうちの 1 つ、またはこれらのキーワードの空白で区切られたリスト。
table-ref

データを更新する既存のテーブルの名前。テーブルで更新を実行するビューを指定できます。この引数でテーブル値関数や JOIN 構文を指定することはできません。

テーブル名 (またはビュー名) は修飾 (schema.table)、未修飾 (table) のどちらでもかまいません。未修飾の名前は、スキーマ検索パス (指定されている場合) または既定のスキーマ名を使用して、そのスキーマと照合されます。

AS t-alias オプションtable-ref (テーブルまたはビュー) の名前のエイリアス。エイリアスは有効な識別子である必要があります。AS キーワードはオプションです。
FROM select-table

オプション — 更新する行を特定する際に使用されるテーブルを指定するために使用される FROM 節。

複数のテーブルは、コンマ区切りのリストとして指定するか、ANSI 結合キーワードで関連付けることができます。テーブルあるいはビューのあらゆる組み合わせを指定できます。ここで 2 つの select-table の間にコンマを指定する場合、InterSystems IRIS は複数のテーブルに CROSS JOIN を実行して、JOIN 処理の結果テーブルからデータを取得します。ここで 2 つの select-table の間に ANSI 結合キーワードを指定する場合、InterSystems IRIS は指定された結合処理を実行します。詳細は、このドキュメントの "JOIN" のページを参照してください。

オプションで、クエリ実行を最適化するために、1 つ以上の optimize-option キーワードを指定できます。使用可能なオプションは、%ALLINDEX、%FIRSTTABLE select-table、%FULL、%INORDER、%IGNOREINDICES、%NOFLATTEN、%NOMERGE、%NOSVSO、%NOTOPOPT、%NOUNIONOROPT、%PARALLEL、および %STARTTABLE です。詳細は、"FROM" 節を参照してください。

WHERE condition-expression オプション — 更新する行を決定する 1 つまたは複数のブーリアン述語を指定します。WHERE 節 (または WHERE CURRENT OF 節) が指定されていない場合、UPDATE はテーブル内のすべての行を更新します。 詳細は、"WHERE" 節を参照してください。
WHERE CURRENT OF cursor オプション : 埋め込み SQL のみUPDATE 操作が、現在のカーソル位置のレコードを更新することを指定します。WHERE CURRENT OF 節または WHERE 節を指定することができます (両方は不可)。詳細は、"WHERE CURRENT OF" を参照してください。
column オプション — 既存の列名。複数の列名はコンマ区切りのリストで指定します。省略した場合は、すべての列が更新されます。
scalar-expression スカラ式で表す列データの値。複数のデータ値はコンマ区切りリストで指定します。各データ値は列の並びに対応します。
array() 埋め込み SQL のみホスト変数として指定する値の配列。配列の最下位の添え字は指定しないでください。:myupdates():myupdates(5,)、および :myupdates(1,1,) はすべて、有効な指定になります。

概要

UPDATE コマンドは、テーブルの列の既存値を変更します。テーブルのデータの更新には、直接行う方法、ビューを使用した方法、または括弧で囲んだサブクエリを使用した方法があります。ビューを使用して更新する場合は、CREATE VIEW で説明されているように、必要条件や制限事項に従います。

UPDATE コマンドにより、1 つ以上の新しい列の値が、それらの列を含む既存のベース・テーブルの 1 つ以上の行に入ります。データ値の列への割り当ては、value-assignment-statement を使用して行われます。既定では、value-assignment-statement はテーブルのすべての行で更新されます。

UPDATE を使用する場合、一般的には condition-expression に基づいて更新する行を指定します。既定では、UPDATE 処理はテーブルのすべての行をチェックし、condition-expression を満たすすべての行を更新します。condition-expression を満たす行がない場合、UPDATE は正常に終了して SQLCODE=100 (データがこれ以上ありません) を設定します。

WHERE 節または WHERE CURRENT OF 節を指定することができます (両方は不可)。WHERE CURRENT OF 節が使用される場合、UPDATE は現在のカーソル位置のレコードを更新します。指定位置での実行の詳細は、"WHERE CURRENT OF" を参照してください。

また、UPDATE 操作により、%ROWCOUNT ローカル変数に更新された行数が設定され、%ROWID ローカル変数に最後に更新された行の RowID 値が設定されます。

既定では、UPDATE オペレーションは全か無かのイベントです。指定された行および列をすべて更新するか、まったくしないかのいずれかです。

INSERT OR UPDATE

INSERT OR UPDATE 文は INSERT 文のバリアントであり、挿入操作と更新操作の両方を実行します。この文は最初に、挿入操作を実行しようとします。UNIQUE KEY 違反が原因で挿入要求に失敗した場合 (いずれかの一意キーのフィールドについて、この挿入対象として指定された行と同じ値を持つ既存の行が存在する場合)、挿入要求はその行に対する更新要求に自動的に変化し、INSERT OR UPDATE が指定されたフィールド値を使用して既存の行を更新します。

SQLCODE エラー

既定では、複数行の UPDATE はアトミック処理です。1 行または複数行の更新できない行があると、UPDATE 処理は失敗し、どの行も更新されません。InterSystems IRIS は、UPDATE の成功または失敗を示す変数 SQLCODE を設定します。操作が失敗した場合は、%msg も設定します。テーブルを更新するには、以下に示すように、更新がすべてのテーブル、列名、および値の各要件を満たしている必要があります。

テーブル :

  • テーブルは、現在の (または指定された) ネームスペースに存在している必要があります。指定されたテーブルが見つからない場合、InterSystems IRIS は SQLCODE -30 エラーを発行します。

  • テーブルを READONLYOpens in a new tab として定義することはできません。読み取り専用テーブルを参照する UPDATE をコンパイルしようとすると、SQLCODE -115 エラーが返されます。このエラーは実行時に発生するのではなく、コンパイル時に発生することに注意してください。"クラスの定義と使用" の "永続クラスのその他のオプション" の章で READONLY オブジェクトの説明を参照してください。

  • 他のプロセスはテーブルを IN EXCLUSIVE MODE でロックできません。ロックされているテーブルを更新しようとすると、SQLCODE -110 エラーになり、%msg は "RowID = '10' の行でテーブル 'Sample.Person' の UPDATE ロックを獲得できません" になります。SQLCODE -110 エラーは、UPDATE 文が更新する最初のレコードを検出した場合にのみ発生し、タイムアウト期間内はロックできません。

  • UPDATE で、存在しないフィールドを指定すると、SQLCODE -29 が発行されます。指定したテーブルのために定義されているすべてのフィールド名をリストするには、"InterSystems SQL の使用法" の “テーブルの定義” の章の "列の名前と番号" を参照してください。フィールドは存在するが UPDATE コマンドの WHERE 節の条件を満たすフィールド値がない場合は、影響を受ける行はないため、SQLCODE 100 (データの末尾) が発行されます。

  • まれに、%NOLOCK が指定された UPDATE で更新する行が見つかったが別のプロセスによりその行が即座に削除された場合には、SQLCODE -109 エラー : "UPDATE に指定された行が見つかりません" が返されます。このエラーの %msg は、テーブル名と RowID をリストします。

  • ビュー経由でテーブルを更新する場合、ビューを WITH READ ONLY として定義することはできません。これを実行しようとすると、SQLCODE -35 エラーが返されます。ビューがシャード・テーブルに基づく場合、WITH CHECK OPTION で定義されたビュー を介して UPDATE を実行することはできません。これを試みると、SQLCODE -35 が生じ、%msg が “シャード・テーブルに基づくビュー (sample.myview) に対し、with check option の条件で INSERT/UPDATE/DELETE を実行することはできません” に設定されます。詳細は、"CREATE VIEW" コマンドを参照してください。

列名と値 :

  • 更新に重複するフィールド名を含めることはできません。同じ名前の 2 つのフィールドを指定する更新を実行しようとすると、SQLCODE -377 エラーが返されます。

  • 別の同時プロセスによってロックされているフィールドは更新できません。これを実行しようとすると、SQLCODE -110 エラーが返されます。大量の更新を実行したことによって <LOCKTABLEFULL> エラーが発生した場合にも、この SQLCODE エラーが発生することがあります。

  • 整数カウンタ・フィールドは更新できません。これらのフィールドは変更不可です。変更すると、以下のエラーが生成されます : RowID フィールド (SQLCODE -107)、IDENTITY フィールド (SQLCODE -107)、SERIAL (%Library.CounterOpens in a new tab) フィールド (SQLCODE -105)、ROWVERSION フィールド (SQLCODE -138)。これらのフィールドの値はシステムで生成され、ユーザは変更できません。ユーザはカウンタ・フィールドの初期値を挿入できても、値を更新することはできません。

    1 つの例外は、既存のデータを含むテーブルに SERIAL (%Library.CounterOpens in a new tab) フィールドを追加する場合です。この追加されたカウンタ・フィールドの既存のレコードには、NULL が含まれます。この場合、UPDATE を使用して NULL を整数値に変更できます。詳細は、"ALTER TABLE" コマンドを参照してください。

  • シャード・キー・フィールドは更新できません。シャード・キーの一部であるフィールドを更新しようとすると、SQLCODE -154 エラーが生成されます。

  • 更新内容がフィールドの一意制約に違反する場合は、フィールド値を更新できません。一意制約または主キー制約に違反するようなフィールド (またはフィールドのグループ) の値の更新を試みると、SQLCODE -120 エラーが発生します。このエラーは、フィールドに UNIQUE データ制約がある場合、またはフィールドのグループに複数フィールドでの一意制約が適用されている場合に返されます。SQLCODE -120 %msg 文字列には、一意制約に違反するフィールドおよび値が含まれています。例えば、<Table 'Sample.MyTable', Constraint 'MYTABLE_UNIQUE3', Field(s) FullName="Molly Bloom"; failed unique check><Table 'Sample.MyTable', Constraint 'MYTABLE_PKEY2', Field(s) FullName="Molly Bloom"; failed unique check> などです。テーブルの一意の値や主キー・フィールドの制約、および制約の名前のリストの詳細は、[カタログの詳細] の [制約] を参照してください。

  • 更新で VALUELIST パラメータにリストされていない値を指定する場合、フィールド値は更新できません。VALUELIST パラメータで定義された永続クラスのプロパティは、有効な値として、VALUELIST でリストされたいずれかのみを受け入れることができ、それ以外の場合は値なし (NULL) が指定されます。VALUELIST の有効な値では、大文字と小文字が区別されます。VALUELIST の値と一致しないデータ値で更新を試みると、SQLCODE -105 のフィールド値検証失敗のエラーが発生します。

  • 数値はキャノニック形式で挿入されますが、先頭と末尾の 0 や、先頭の複数の符号を付けて指定できます。ただし、SQL では、2 つの連続したマイナス記号は、1 行コメント文字として解析されます。したがって、先頭に 2 つの連続したマイナス符号を付けて数値を指定しようとすると、SQLCODE -12 エラーになります。

  • WHERE CURRENT OF 節を使用する場合は、現在のフィールド値を使用して新しい値を生成してフィールドを更新することはできません。例としては、SET Salary=Salary+100SET Name=UPPER(Name) が挙げられます。これを実行しようとすると、SQLCODE -69 エラーが返されます。SET <field> = <value expression> を WHERE CURRENT OF <cursor> で使用できません。

  • 指定された行の 1 行の更新が外部キーの参照整合性に違反する場合 (かつ %NOCHECK が指定されていない場合)、UPDATE はいずれの行も更新せず、SQLCODE -124 エラーが発行されます。これは、NOCHECK キーワードを使用して外部キーを定義している場合には適用されません。

  • 非ストリーム・フィールドをストリーム・データで更新することはできません。これにより、以下に示すように SQLCODE -303 エラーが発生します。

  • 挿入されるデータ値は表示モードから論理モードへの変換に合格する必要があります。InterSystems SQL では、データを logical モード形式で格納します。一部のデータ型では、論理形式が表示形式と異なることがあります。例えば、日付データは日数を示す整数値として格納され、時刻データは午前 0 時 00 分からの秒数として格納され、%List データはエンコードされた文字列として格納されます。文字列や数値など、その他のデータ型の場合、変換は必要ありません。論理格納値に変換できない形式で値を挿入しようとすると、エラーが発生します (日付の場合は SQLCODE -146、時刻の場合は SQLCODE -147)。モード変換の詳細は、"データ表示オプション" を参照してください。

値の割り当て

さまざまな方法で新しい値を、指定した列に割り当てることができます。

  • SET キーワードを使用して、1 つ以上の column = scalar-expression のペアをコンマ区切りリストとして指定します。以下に例を示します。

    SET StatusDate='05/12/06',Status='Purged'
    
  • VALUES キーワードを使用して、列のリストとそれに対応するスカラ式のリストを指定します。以下に例を示します。

    (StatusDate,Status) VALUES ('05/12/06','Purged')
    

    スカラ式の値を列のリストに割り当てる場合、指定する列ごとにスカラ式が必要です。

  • 列リストを指定せずに VALUES キーワードを使用する場合、行の列の列順と暗黙的に対応するスカラ式のリストを指定します。以下の例では、テーブル内のすべての列を指定し、Address 列を更新するためのリテラル値を指定しています。

    VALUES (Name,DOB,'22 Main St. Anytown MA 12345',SSN)
    

    値を暗黙の列リストに割り当てるときには、DDL で列が定義されている順序で、すべての更新可能フィールドに値を指定する必要があります (更新できない RowID 列は指定されません)。これらの値は、新規の値を指定するリテラルまたは既存の値を指定するフィールド名のいずれかにすることができます。プレースホルダとしてのコンマを指定したり、末尾のフィールドを省略したりすることはできません。

  • 列リストなしで VALUES キーワードを使用すると、数値添え字が列番号と対応している、添え字付き配列が指定されます。列数には更新できない RowID が列番号 1 として含まれます。例えば以下のようになります。

    VALUES :myarray()
    

    この値の割り当ては、埋め込み SQL からホスト変数を使用することでのみ実行できます。その他すべての値の割り当てと異なり、この使用方法では (実行時に配列を追加することで) 更新する列の指定を実行時まで遅らせることができます。その他すべてのタイプの更新では、コンパイル時に更新する列を指定する必要があります。この構文はリンク・テーブルと一緒には使用できません。併用しようとすると、SQLCODE =-155 エラーが返されます。詳細は、"InterSystems SQL の使用法" の “埋め込み SQL の使用法” の章の “添え字付き配列としてのホスト変数” を参照してください。

これらの UPDATE の各タイプを示すプログラム例については、後述の "" のセクションを参照してください。

DISPLAY から LOGICAL へのデータ変換

更新されるデータ値は表示モードから論理モードへの変換に合格する必要があります。InterSystems SQL では、データを logical モード形式で格納します。一部のデータ型では、論理形式が表示形式と異なることがあります。例えば、日付データは日数を示す整数値として格納され、時刻データは午前 0 時 00 分からの秒数として格納され、%List データはエンコードされた文字列として格納されます。文字列や数値など、その他のデータ型の場合、変換は必要ありません。論理格納値に変換できない形式で値を挿入しようとすると、エラーが発生します。モード変換の詳細は、"データ表示オプション" を参照してください。

リスト構造

InterSystems IRIS は、リスト構造のデータ型 %List (データ型クラス %Library.List) をサポートしています。これは圧縮バイナリ形式であり、InterSystems SQL で対応するネイティブなデータ型にマップしません。また、データ型 VARBINARY に対応しており、その MAXLEN の既定値は 32749 です。このため、ダイナミック SQL では、型 %List のプロパティ値を設定するときに、UPDATEINSERT も使用できません。詳細は、このドキュメントのリファレンスの "データ型" を参照してください。

ストリーム値

以下のように、ストリーム・フィールド内のデータ値を更新できます。

  • 任意のテーブル : 文字列リテラル、または文字列リテラルが含まれるホスト変数。以下に例を示します。

        SET literal="update stream string value"
           //do the update; use a string
        &sql(UPDATE MyStreamTable SET MyStreamField = :literal WHERE %ID=21)
  • シャード化されていないテーブル : ストリーム・オブジェクトへのオブジェクト参照 (OREF)。InterSystems IRIS は、このオブジェクトを開いてそのコンテンツをコピーし、ストリーム・フィールドを更新します。以下に例を示します。

        SET oref=##class(%Stream.GlobalCharacter).%New()
        DO oref.Write("Update stream string value non-shard 1")
           //do the update; use an actual OREF
        &sql(UPDATE MyStreamTable SET MyStreamField = :oref WHERE %ID=22)

    または、ストリームの文字列版 OREF。以下はその例です。

        SET oref=##class(%Stream.GlobalCharacter).%New()
        DO oref.Write("Update stream string value non-shard 2")
           //next line converts OREF to a string OREF
        set string=oref_""
           //do the update
        &sql(UPDATE MyStreamTable SET MyStreamField = :string WHERE %ID=23)
  • シャード・テーブル : ^IRIS.Stream.Shard グローバルに保存されている一時ストリーム・オブジェクトを使用するオブジェクト ID (OID)。

        SET clob=##class(%Stream.GlobalCharacter).%New("Shard")
        DO clob.Write("Update sharded table stream string value")
        SET sc=clob.%Save() // Handle $$$ISERR(sc)
        set ClobOid=clob.%Oid()
        //do the update
        &sql(UPDATE MyStreamTable SET MyStreamField = :ClobOid WHERE %ID=24)

非ストリーム・フィールドをストリーム・フィールドのコンテンツで更新することはできません。これを実行すると、SQLCODE -303 エラー : “UPDATE 割り当てでストリーム・フィールドから非ストリーム・フィールド への暗黙の変換はありません” が返されて失敗します。文字列フィールドをストリーム・データで更新するには、以下の例のように、最初に SUBSTRING 関数を使用してストリーム・データの最初の n 文字を文字列に変換する必要があります。

UPDATE MyTable
     SET MyStringField=SUBSTRING(MyStreamField,1,2000)

計算フィールド

COMPUTECODE を指定して定義されているフィールドは、以下のように、UPDATE 処理の一部として値を再計算できます。.

  • COMPUTECODE:値は、計算されて INSERT 時に保存されます。UPDATE 時には変更されません。

  • COMPUTEONCHANGE の COMPUTECODE:値は、計算されて INSERT 時に保存されます。UPDATE 時には再計算されて保存されます。

  • DEFAULT と COMPUTEONCHANGE の COMPUTECODE:既定値は、INSERT 時に保存されます。値は、UPDATE 時に計算されて保存されます。計算コードにプログラミング・エラーがある場合 (例えば、ゼロでの除算)、UPDATE 操作は SQLCODE -415 エラーで失敗します。

  • CALCULATED または TRANSIENT が指定された COMPUTECODE:このフィールドには値が格納されないので、値の UPDATE は実行できません。値は照会されるときに計算されます。ただし、計算済みフィールド内の値を更新しようとすると、InterSystems IRIS は指定された値に対する検証を実行し、値が無効であればエラーを発行します。値が有効である場合、InterSystems IRIS は更新操作を実行せず、SQLCODE エラーを発行せず、ROWCOUNT をインクリメントします。

UPDATE 処理の新しいフィールド値が以前のフィールド値と同じである場合、実際の更新が発生しなければ、COMPUTEONCHANGE 計算フィールドは再計算されません。

ほとんどの場合、計算フィールドは読み取り専用として定義します。これによって、他のフィールド値が関与する計算の結果とされる値が、更新処理によって直接変更されないようになります。この場合、計算フィールドの値を上書きする UPDATE を使用しようとすると、SQLCODE -138 エラーが発生します。

ただし、1 つ (以上) のソース・フィールド値の更新を反映できるように、計算フィールド値を改訂することもできます。このような改訂は、指定されたソース・フィールドを更新した後に計算フィールド値を再計算する更新トリガを使用することで実行できます。例えば、Salary データ・フィールドの更新によって、Bonus 計算フィールドを再計算するトリガを起動したとします。この更新トリガによって Bonus が再計算され、Bonus が読み取り専用フィールドであっても正常に完了します。"CREATE TRIGGER" 文を参照してください。

CREATE TABLE ON UPDATE キーワード句を使用して、レコードが更新されるときにリテラルまたはシステム変数に設定されるフィールド (現在のタイムスタンプなど) を定義できます。

詳細は、"INSERT または UPDATE 時の計算フィールドの値" を参照してください。

%SerialObject プロパティ

%SerialObject でデータを更新する際は、埋め込み %SerialObject を参照するテーブル (永続クラス) を更新する必要があります。%SerialObject を直接更新することはできません。参照するテーブルから、以下のいずれかを実行できます。

  • 参照するフィールドを使用して、複数の %SerialObject プロパティの値を %List 構造として更新する。例えば、永続クラスに、プロパティ Street、City、および Country をこの順序で含むシリアル・オブジェクトを参照するプロパティ PAddress がある場合、SET PAddress=$LISTBUILD('123 Main St.','Newtown','USA')(PAddress) VALUES ($LISTBUILD('123 Main St.','Newtown','USA'))、または (PAddress) VALUES (:vallist) を更新します。%List には、シリアル・オブジェクト (またはプレースホルダとしてのコンマ) のプロパティの値が、このシリアル・オブジェクトで指定されている順序で含まれる必要があります。

    このタイプの更新では、%SerialObject プロパティ値の検証は実行されない場合があります。したがって、%List 構造を使用して %SerialObject プロパティ値を更新した後に、$SYSTEM.SQL.Schema.ValidateTable() メソッドを使用してテーブル・データの検証を実行することを強くお勧めします。

  • アンダースコア構文を使用して、個々の %SerialObject プロパティの値を任意の順序で更新する。例えば、永続クラスに、プロパティ Street、City、および Country を含むシリアル・オブジェクトを参照するプロパティ PAddress がある場合、SET PAddress_City='Newtown',PAddress_Street='123 Main St.',PAddress_Country='USA' を更新します。

    このタイプの更新では、%SerialObject プロパティ値の検証が実行されます。

FROM 節

UPDATE コマンドでは FROM キーワードを省略できます。更新するテーブル (またはビュー) を指定し、更新する行を WHERE 節を使用して選択するだけでもかまいません。

ただし、value-assignment-statement の後に FROM 節をオプションで含めることもできます。この FROM 節では、更新するレコードを特定するために使用される 1 つ以上のテーブルを指定します。この FROM 節は、通常は (常にではありませんが) 複数のテーブルを含む WHERE 節と共に使用します。FROM 節は複雑にすることができ、ANSI 結合構文を含めることができます。SELECT FROM 節でサポートされている構文はすべて、UPDATE FROM 節で許可されています。この UPDATE FROM 節は、Transact-SQL との機能的な互換性を提供します。

以下の例は、この FROM 節の使用法を示しています。ここでは、Retirees テーブル内に同じ EmpId がある場合、それらのレコードが Employees テーブルで更新されます。

UPDATE Employees AS Emp
     SET retired='Yes'
     FROM Retirees AS Rt
     WHERE Emp.EmpId = Rt.EmpId

UPDATE table-ref と FROM 節で同じテーブルを参照する場合には、参照するテーブルが文字どおり同じであることも、テーブルの 2 つのインスタンスの結合であることもあります。これは、テーブルのエイリアスの使用方法によって異なります。

  • 両方のテーブル参照にエイリアスがない場合には、両方とも同じテーブルを参照します。

      UPDATE table1 value-assignment FROM table1,table2   /* join of 2 tables */
    
  • 両方のテーブル参照に同じエイリアスがある場合には、両方とも同じテーブルを参照します。

      UPDATE table1 AS x value-assignment FROM table1 AS x,table2   /* join of 2 tables */
    
  • 両方のテーブル参照にエイリアスがあり、それぞれのエイリアスが異なる場合には、InterSystems IRIS は 2 つのテーブルのインスタンスの結合を実行します。

      UPDATE table1 AS x value-assignment FROM table1 AS y,table2   /* join of 3 tables */
    
  • 最初のテーブル参照にエイリアスがあり、2 番目にはない場合には、InterSystems IRIS は 2 つのテーブルのインスタンスの結合を実行します。

      UPDATE table1 AS x value-assignment FROM table1,table2   /* join of 3 tables */
    
  • 最初のテーブル参照にエイリアスがなく、2 番目にはエイリアスのあるテーブルへの単一の参照がある場合には、両方とも同じテーブルを参照し、このテーブルには指定されたエイリアスがあります。

      UPDATE table1 value-assignment FROM table1 AS x,table2   /* join of 2 tables */
    
  • 最初のテーブル参照にエイリアスがなく、2 番目にはテーブルへの複数の参照がある場合には、それぞれのエイリアスされたインスタンスは個別のテーブルと見なされ、それらのテーブルの結合が実行されます。

      UPDATE table1 value-assignment FROM table1,table1 AS x,table2        /* join of 3 tables */
      UPDATE table1 value-assignment FROM table1 AS x,table1 AS y,table2   /* join of 4 tables */
    
    

%Keyword 引数

%keyword 引数を指定すると、以下のように処理を制限します。

  • %NOCHECK — 一意の値のチェックおよび外部キーの参照整合性チェックは実行されません。データ型、最大長、データ制約などの検証条件に関して、列データの検証も実行されません。ビューを介して UPDATE を実行する場合、ビューの WITH CHECK OPTION 検証は実行されません。

    Note:

    %NOCHECK を使用すると、無効なデータが発生する場合があるため、この %keyword 引数の使用は、信頼性の高いデータ・ソースから挿入または更新を一括で実行する場合に限定してください。

    この制限を適用するには、ユーザは、現在のネームスペースに対して対応する %NOCHECK 管理特権を持っている必要があります。持っていない場合、SQLCODE –99 エラーが発生し、%msg が "ユーザ 'name' は %NOCHECK 特権を持っていません" に設定されます。

    %NOCHECK を指定する際に、更新で一意でないデータ値が生じないようにしたい場合は、UPDATE の前に EXISTS チェックを実行します。

    外部キーの参照整合性チェックのみを無効にしたい場合は、%NOCHECK を指定するのではなく $SYSTEM.SQL.Util.SetOption("FilerRefIntegrity")Opens in a new tab メソッドを使用します。または、NOCHECK キーワードを使用して外部キーを定義し、外部キーの参照整合性チェックが実行されないようにすることができます。

  • %NOFPLAN — FROM 節の構文のみ:この操作の凍結されたプラン (ある場合) を無視して、新しいクエリ・プランを生成します。凍結されたプランは保持されますが、使用されません。詳細は、“SQL 最適化ガイド” の “凍結プラン” を参照してください。

  • %NOINDEX — インデックス・マップは UPDATE 処理中には設定されません。この制限を適用するには、ユーザは、現在のネームスペースに対して対応する %NOINDEX 管理特権を持っている必要があります。これを実行しないと、SQLCODE -99 エラーが返されます。

  • %NOJOURN — 更新操作の間、ジャーナリングを抑制し、トランザクションを無効化します。プルされたトリガを含め、行での変更はどれもジャーナリングされません。ただし、更新は依然としてミラーリングされている環境でジャーナリングされます。%NOJOURN が指定された文の後で ROLLBACK を実行した場合、その文で行われた変更はロールバックされません。この制限を適用するには、現在のネームスペースに対応する %NOJOURN 管理特権がユーザに必要です。これを実行しないと、SQLCODE -99 エラーが返されます。

  • %NOLOCK — UPDATE 時に行をロックしません。単独のユーザ/処理がデータベースを更新する際にのみ使用します。この制限を適用するには、ユーザは、現在のネームスペースに対して対応する %NOLOCK 管理特権を持っている必要があります。これを実行しないと、SQLCODE -99 エラーが返されます。

  • %NOTRIGGER — ベース・テーブル・トリガは UPDATE 処理中にはかかりません。BEFORE トリガおよび AFTER トリガのどちらも実行されません。この制限を適用するには、ユーザは、現在のネームスペースに対して対応する %NOTRIGGER 管理特権を持っている必要があります。これを実行しないと、SQLCODE -99 エラーが返されます。

  • %PROFILE または %PROFILE_ALL — これらのキーワード指示文のいずれかが指定された場合、SQLStats 収集コードが生成されます。これは、PTools を ON にして生成されるものと同じコードです。違いは、SQLStats 収集コードはこの特定の文に対してのみ生成されるという点です。コンパイルされるルーチン/クラス内のその他すべての SQL 文は、PTools が OFF であるかのようにコードを生成します。これにより、ユーザは、調査されない SQL 文の関係のない統計を収集することなく、アプリケーション内の特定の問題の SQL 文をプロファイリング/調査できます。詳細は、“InterSystems SQL 最適化ガイド” の “SQL 実行時統計” を参照してください。

    %PROFILE はメイン・クエリ・モジュールに対して SQLStats を収集します。%PROFILE_ALL はメイン・クエリ・モジュールとそのすべてのサブクエリ・モジュールに対して SQLStats を収集します。

複数の %keyword 引数を順不同で指定できます。複数の引数は、空白で区切られます。

参照整合性

%NOCHECK を指定しない場合、InterSystems IRIS では、システム全体の構成設定を使用して外部キーの参照整合性チェックを実行するかどうかが決まります。既定では、外部キーの参照整合性チェックを実行します。"外部キーの参照整合性チェック" の説明に従って、この既定値をシステム全体で設定できます。現在のシステム全体の設定を確認するには、$SYSTEM.SQL.CurrentSettings()Opens in a new tab を呼び出します。

この設定は、NOCHECK キーワードを使用して定義した外部キーには適用されません。

UPDATE 処理中は、更新するフィールド値を持つ外部キーの参照があるたびに、参照するテーブルの古い (更新前の) 参照行と新しい (更新後の) 参照行の両方で共有ロックを取得します。これらの行は参照整合性チェックと行の更新が完了するまでロックされます。その後、ロックは解除されます (トランザクションの終了までロック状態が継続することはありません)。このロックによって、参照整合性チェックから更新操作の完了までの間、参照先の行が変更されないようになります。古い行をロックすることにより、参照される行は、UPDATE のロールバックがあってもそれより前に変更されることがなくなります。新しい行をロックすることにより、参照整合性チェックから更新操作の完了までの間、参照先の行が変更されないようになります。

CASCADE、SET NULL、または SET DEFAULT で定義された外部キー・フィールドに対して、%NOLOCK を指定して UPDATE 操作を実行した場合は、対応する参照アクションが %NOLOCK によって実行されて外部キー・テーブルが変更されます。

アトミック性

既定では、UPDATEINSERTDELETE、および TRUNCATE TABLE はアトミック処理として実行されます。UPDATE は、正常に完了するか、すべての操作がロールバックされるかのいずれかです。指定した行のいずれかを更新できない場合、指定した行は 1 行も更新できずにデータベースは UPDATE を発行する前の状態に戻ります。

現在のプロセスに対するこの既定は、SET TRANSACTION %COMMITMODE を呼び出すことによって SQL 内で変更できます。現在のプロセスに対するこの既定は、SetOption()Opens in a new tab メソッドを SET status=$SYSTEM.SQL.Util.SetOption("AutoCommit",intval,.oldval) のように呼び出すことによって ObjectScript 内で変更できます。以下の intval 整数オプションを使用できます。

  • 1 または IMPLICIT (自動コミットがオン) — 上記のように、これが既定の動作です。UPDATE ごとに個別のトランザクションが構成されます。

  • 2 または EXPLICIT (自動コミットがオフ) — 進行中のトランザクションがない場合は、UPDATE コマンドによってトランザクションは自動的に開始されます。ただし、COMMIT または ROLLBACK で明示的にトランザクションを終了する必要があります。EXPLICIT モードでは、トランザクションあたりのデータベース操作の数は、ユーザ定義です。

  • 0 または NONE (自動トランザクションなし) — UPDATE を呼び出してもトランザクションは開始されません。UPDATE 操作の失敗により、行の一部が更新されたり更新されなかったりすることで、データベースが整合性のない状態になる可能性があります。このモードでトランザクションのサポートを提供するには、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 を指定しない場合、INSERTUPDATE、および DELETE 操作時に自動的にレコードに標準のロックがかかります。影響を受ける各レコード (行) は、現在のトランザクションが継続している間はロックされます。

既定のロックしきい値は、テーブルごとに 1000 ロックです。つまり、トランザクションの間にテーブルで 1000 件を超えるレコードを更新すると、ロックのしきい値に到達し、InterSystems IRIS は自動的にロック・レベルをレコード・ロックからテーブル・ロックに上げます。これによってトランザクション時に、ロック・テーブルをオーバーフローすることなく、大規模な更新を実行できます。

InterSystems IRIS は、以下の 2 つのロック・エスカレーション策のどちらかを適用します。

  • “E” タイプのロック・エスカレーション: InterSystems IRIS は、次のことに該当する場合にこのタイプのロック・エスカレーションを使用します。(1) クラスで %Storage.Persistent が使用されている (これは、管理ポータルの SQL スキーマ表示で [カタログの詳細] から判断できます)。(2) クラスで、IDKey インデックスが指定されていないか、単一プロパティの IDKey インデックスが指定されている。“E” タイプのロック・エスカレーションについては、"ObjectScript リファレンス" の LOCK コマンドで説明されています。

  • 従来の SQL ロック・エスカレーション:クラスで “E” タイプのロック・エスカレーションが使用されない理由は、マルチプロパティの IDKey インデックスの存在にあると考えられます。この場合は、%Save ごとにロック・カウンタがインクリメントされます。つまり、トランザクション内の単一オブジェクトを 1001 回保存を行うと、InterSystems IRIS はロックのエスカレーションを試みます。

どちらのロック・エスカレーション策の場合も、$SYSTEM.SQL.Util.GetOption("LockThreshold")Opens in a new tab メソッドを使用して、現在のシステム全体用ロックしきい値を決定できます。既定値は 1,000 です。このシステム全体のロックしきい値は、以下の方法を使用して設定できます。

  • $SYSTEM.SQL.Util.SetOption("LockThreshold")Opens in a new tab メソッドを使用します。

  • 管理ポータルを使用する。[システム管理][構成][SQL およびオブジェクトの設定][SQL] の順に移動します。[ロック・エスカレーションしきい値] の現在の設定を表示して編集します。既定は 1000 ロックです。この設定を変更すると、変更後に開始される新しいプロセスは、新しい設定になります。

ロックしきい値を変更するには、%Admin Manage Resource の USE 許可が必要です。InterSystems IRIS は、ロックしきい値の変更を現在のプロセスすべてに即座に適用します。

結果として、自動ロック・エスカレーションでは、デッドロックの状況が起こる可能性があります。つまり、テーブル・ロックへのエスカレーションを試みたときに、テーブル内のレコード・ロックを保持する別プロセスとの競合が起こる可能性があります。これを避けるための方策としては、次のいくつかが考えられます。 (1) ロック・エスカレーションがトランザクション内で起こる可能性が低くなるように、ロック・エスカレーションのしきい値を上げる。(2) ロック・エスカレーションが即座に起こるように、ロック・エスカレーションのしきい値を大幅に下げる。これにより、別プロセスが同一テーブル内のレコードをロックする機会が少なくなります。(3) トランザクションが継続している間はテーブル・ロックを適用し、レコード・ロックは実行しない。これは、LOCK TABLE、UNLOCK TABLE (テーブル・ロックがトランザクションの終了まで持続するよう、IMMEDIATE キーワードはなし) の順に指定することで、トランザクション開始時に実行できます。その後、%NOLOCK オプションを使用して更新を実行します。

自動ロック・エスカレーションは、ロック・テーブルのオーバーフローを防ぐことを目的としています。ただし、大量の更新などを実行したために <LOCKTABLEFULL> エラーが発生した場合は、UPDATE によって SQLCODE -110 エラーが発行されます。

トランザクションでのロックの詳細は、"InterSystems SQL の使用法" の “データベースの変更“ の章にある "トランザクション処理" を参照してください。

カウンタのインクリメント

  • ROWVERSION

  • SERIAL (%Counter)

ROWVERSION カウンタのインクリメント

テーブルにデータ型 ROWVERSION のフィールドが存在する場合、行の更新を実行すると、このフィールドの整数値が自動的に更新されます。ROWVERSION フィールドは、ネームスペース全体の行バージョン・カウンタの連続した次の整数を取得します。ROWVERSION フィールドに更新値を指定すると、SQLCODE -138 エラーが返されます。

SERIAL (%Counter) カウンタのインクリメント

UPDATE 操作は、SERIAL (%Library.Counter) カウンタ・フィールドの値に影響しません。ただし、INSERT OR UPDATE を使用して実行される更新では、SERIAL フィールドに対する後続の挿入操作で整数シーケンスのスキップが発生します。詳細は "IINSERT OR UPDATE" を参照してください。

特権

更新を実行するには、指定したテーブル (またはビュー) のテーブルレベルの UPDATE 特権、または指定した列の列レベルの UPDATE 特権のいずれかが必要です。行内のすべてのフィールドを更新する場合、列レベルの特権は GRANT コマンドで名付けられたすべてのテーブル列を管理し、テーブルレベルの特権は、特権が割り当てられた後に追加されたものも含み、すべてのテーブル列を管理します。

  • ユーザは指定されたテーブルに対する UPDATE 特権、または UPDATE フィールド・リスト内のすべての列に対する列レベルの UPDATE 特権を持っている必要があります。

  • ユーザは WHERE 節のフィールドに対する SELECT 特権を持っている必要があります (これらのフィールドを更新するかどうかにかかわらず)。これらのフィールドが UPDATE フィールド・リストに含まれる場合には、これらのフィールドに対する SELECT 特権と UPDATE 特権の両方が必要です。以下の例では、Name フィールドには (少なくとも) 列レベルの SELECT 特権が必要です。

    UPDATE Sample.Employee (Salary) VALUES (1000000) WHERE Name='Smith, John'

    上記の例では、Salary フィールドには列レベルの UPDATE 特権のみが必要です。

ユーザがテーブルの所有者 (作成者) である場合、ユーザにはそのテーブルに対するすべての特権が自動的に付与されます。そうでない場合は、ユーザにテーブルに対する特権を付与する必要があります。持っていない場合、SQLCODE –99 エラーが発生し、%msg が "ユーザ 'name' は操作に対する特権を持っていません" に設定されます。%CHECKPRIV コマンドを呼び出すことにより、現在のユーザが適切な特権を持っているかどうかを確認できます。GRANT コマンドを使用してユーザにテーブル特権を割り当てることができます。詳細は、"InterSystems SQL の使用法" の "特権" を参照してください。

プロパティが ReadOnly として定義されている場合、対応するテーブル・フィールドも ReadOnly として定義されています。ReadOnly フィールドに値を割り当てるには、InitialExpression または SqlComputed を使用する必要があります。列レベルの ReadOnly (SELECT または REFERENCES) 特権を持っているフィールドの値 (NULL 値であっても) を更新しようとすると、SQLCODE -138 エラー : "読み取り専用フィールドをINSERT/UPDATEすることはできません" が発生します。リンク・テーブル・ウィザードを使用してテーブルをリンクすると、フィールドを Read Only として定義することができるようになります。ソース・システム上のフィールドが読み取り専用ではないにもかかわらず、InterSystems IRIS でそのリンク・テーブルのフィールドを Read Only として定義した場合、このフィールドを参照する UPDATE を試みると、SQLCODE -138 エラーが発生します。

行レベル・セキュリティ

InterSystems IRIS の行レベル・セキュリティにより、UPDATE を使用して、セキュリティでアクセスが許可されるすべての行を変更できるようになります。セキュリティにより今後のアクセスが許可されない行が UPDATE によって作成された場合でも、行の更新が可能になります。UPDATE により行への今後の SELECT アクセスが妨げられないようにするには、WITH CHECK OPTION を持つビューで UPDATE を実行することをお勧めします。詳細は、"CREATE VIEW" を参照してください。

このセクションの例では、SQLUser.MyStudents テーブルを更新しています。以下の例では、SQLUser.MyStudents テーブルを作成し、そのテーブルにデータを生成しています。この例を繰り返し実行すると、重複データのあるレコードが累積するため、TRUNCATE TABLE を使用して、INSERT を呼び出す前に古いデータを削除します。この例は、UPDATE の例を呼び出す前に実行します。

CreateStudentTable
    SET stuDDL=5
    SET stuDDL(1)="CREATE TABLE SQLUser.MyStudents ("
    SET stuDDL(2)="StudentName VARCHAR(32),StudentDOB DATE,"
    SET stuDDL(3)="StudentAge INTEGER COMPUTECODE {SET {StudentAge}="
    SET stuDDL(4)="$PIECE(($PIECE($H,"","",1)-{StudentDOB})/365,""."",1)} CALCULATED,"
    SET stuDDL(5)="Q1Grade CHAR,Q2Grade CHAR,Q3Grade CHAR,FinalGrade VARCHAR(2))"
  SET tStatement = ##class(%SQL.Statement).%New(0,"Sample")
  SET qStatus = tStatement.%Prepare(.stuDDL)
    IF qStatus'=1 {WRITE "DDL %Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET rtn = tStatement.%Execute()
  IF rtn.%SQLCODE=0 {WRITE !,"Table Create successful"}
  ELSEIF rtn.%SQLCODE=-201 {WRITE "Table already exists, SQLCODE=",rtn.%SQLCODE,!}  
  ELSE {WRITE !,"table create failed, SQLCODE=",rtn.%SQLCODE,!
        WRITE rtn.%Message,! }
RemoveOldData
  SET clearit="TRUNCATE TABLE SQLUser.MyStudents"
  SET qStatus = tStatement.%Prepare(clearit)
   IF qStatus'=1 {WRITE "Truncate %Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET truncrtn = tStatement.%Execute()
  IF truncrtn.%SQLCODE=0 {WRITE !,"Table old data removed",!}
  ELSEIF truncrtn.%SQLCODE=100 {WRITE !,"no data to be removed",!}
  ELSE {WRITE !,"truncate failed, SQLCODE=",truncrtn.%SQLCODE," ",truncrtn.%Message,! }
PopulateStudentTable
  SET studentpop=2
  SET studentpop(1)="INSERT INTO SQLUser.MyStudents (StudentName,StudentDOB) "
  SET studentpop(2)="SELECT Name,DOB FROM Sample.Person WHERE Age <= '21'"
  SET qStatus = tStatement.%Prepare(.studentpop)
    IF qStatus'=1 {WRITE "Populate %Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET poprtn = tStatement.%Execute()
  IF poprtn.%SQLCODE=0 {WRITE !,"Table Populate successful",!
        WRITE poprtn.%ROWCOUNT," rows inserted"}
  ELSE {WRITE !,"table populate failed, SQLCODE=",poprtn.%SQLCODE,!
        WRITE poprtn.%Message }

以下のクエリを使用して、これらの例の結果を表示できます。

SELECT %ID,* FROM SQLUser.MyStudents ORDER BY StudentAge,%ID

以下の UPDATE の例のいくつかは、他の UPDATE の例で設定されるフィールド値に依存しているため、指定された順序で実行する必要があります。

以下のダイナミック SQL の例では、SET field=value UPDATE は、選択したレコード内の指定したフィールドを変更します。MyStudents テーブルでは、7 歳未満の児童には成績が指定されていません。

    SET studentupdate=3
    SET studentupdate(1)="UPDATE SQLUser.MyStudents "
    SET studentupdate(2)="SET FinalGrade='NA' "
    SET studentupdate(3)="WHERE StudentAge <= 6"
  SET tStatement = ##class(%SQL.Statement).%New(0,"Sample")
  SET qStatus = tStatement.%Prepare(.studentupdate)
    IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET uprtn = tStatement.%Execute()
  IF uprtn.%SQLCODE=0 {WRITE !,"Table Update successful"
                       WRITE !,"Rows updated=",uprtn.%ROWCOUNT," Final RowID=",uprtn.%ROWID}
  ELSE {WRITE !,"Table update failed, SQLCODE=",uprtn.%SQLCODE," ",uprtn.%Message }

以下のカーソル・ベースの埋め込み SQL の例では、SET field1=value1,field2=value2 UPDATE は、選択したレコード内のいくつかのフィールドを変更します。MyStudents テーブルで、これは指定した学生レコードを Q1 と Q2 の成績で更新します。

  #sqlcompile path=Sample
  NEW %ROWCOUNT,%ROWID
  &sql(DECLARE StuCursor CURSOR FOR 
        SELECT * FROM MyStudents
        WHERE %ID IN(10,12,14,16,18,20,22,24) AND StudentAge > 6)
   &sql(OPEN StuCursor)
        QUIT:(SQLCODE'=0)
   FOR { &sql(FETCH StuCursor)
        QUIT:SQLCODE 
        &sql(Update MyStudents SET Q1Grade='A',Q2Grade='A'
       WHERE CURRENT OF StuCursor)
    IF SQLCODE=0 {
    WRITE !,"Table Update successful"
    WRITE !,"Row count=",%ROWCOUNT," RowID=",%ROWID }
    ELSE {
    WRITE !,"Table Update failed, SQLCODE=",SQLCODE }
    }
    &sql(CLOSE StuCursor)

以下のダイナミック SQL の例では、field-list VALUES value-list UPDATE は、選択したレコード内のいくつかのフィールドの値を変更します。MyStudents テーブルでは、最終成績を受け取らない児童は、四半期成績も受け取りません。

    SET studentupdate=3
    SET studentupdate(1)="UPDATE SQLUser.MyStudents "
    SET studentupdate(2)="(Q1Grade,Q2Grade,Q3Grade) VALUES ('x','x','x') "
    SET studentupdate(3)="WHERE FinalGrade='NA'"
  SET tStatement = ##class(%SQL.Statement).%New()
  SET qStatus = tStatement.%Prepare(.studentupdate)
   IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET uprtn = tStatement.%Execute()
  IF uprtn.%SQLCODE=0 {WRITE !,"Table Update successful"
                       WRITE !,"Rows updated=",uprtn.%ROWCOUNT," Final RowID=",uprtn.%ROWID}
  ELSE {WRITE !,"Table Update failed, SQLCODE=",uprtn.%SQLCODE," ",uprtn.%Message,! }

以下のダイナミック SQL の例では、VALUES value-list UPDATE は、選択したレコード内のすべてのフィールド値を変更します。この構文では、レコード内のすべてのフィールドの値を指定する必要があります。MyStudents テーブルでは、数人の児童が学校を退学しています。そのレコード ID と名前は保持され、名前に WITHDRAWN が付加されます。その他すべてのデータは削除され、DOB フィールドは退学の日付用に使用されます。

    SET studentupdate=4
    SET studentupdate(1)="UPDATE SQLUser.MyStudents "
    SET studentupdate(2)="VALUES (StudentName||' WITHDRAWN',"
    SET studentupdate(3)="$PIECE($HOROLOG,',',1),00,'-','-','-','XX') "
    SET studentupdate(4)="WHERE %ID IN(7,10,22)"
  SET tStatement = ##class(%SQL.Statement).%New()
  SET qStatus = tStatement.%Prepare(.studentupdate)
    IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET uprtn = tStatement.%Execute()
  IF uprtn.%SQLCODE=0 {WRITE !,"Table Update successful"
                       WRITE !,"Rows updated=",uprtn.%ROWCOUNT," Final RowID=",uprtn.%ROWID}
  ELSE {WRITE !,"Table Update failed, SQLCODE=",uprtn.%SQLCODE," ",uprtn.%Message,! }

以下のダイナミック SQL の例では、subquery UPDATE はレコードの選択にサブクエリを使用しています。次にそれらのレコードを SET field=value 構文を使用して変更しています。SQLUser.MyStudents にある誕生日から StudentAge を計算する方法により、1 歳未満の児童の年齢は <Null> と算出されており、誕生日が NULL となっている児童は算出年齢がかなり高くなっています。ここで StudentName フィールドには、後で誕生日を確認するためにフラグが付けられています。

    SET studentupdate=3
    SET studentupdate(1)="UPDATE (SELECT StudentName FROM SQLUser.MyStudents "
    SET studentupdate(2)="WHERE StudentAge IS NULL OR StudentAge > 21) "
    SET studentupdate(3)="SET StudentName = StudentName||' *** CHECK DOB' "
  SET tStatement = ##class(%SQL.Statement).%New(0,"Sample")
  SET qStatus = tStatement.%Prepare(.studentupdate)
    IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET uprtn = tStatement.%Execute()
  IF uprtn.%SQLCODE=0 {WRITE !,"Table Update successful"
                       WRITE !,"Rows updated=",uprtn.%ROWCOUNT," Final RowID=",uprtn.%ROWID}
  ELSE {WRITE !,"Table Update failed, SQLCODE=",uprtn.%SQLCODE," ",uprtn.%Message,! }

以下の埋め込み SQL の例では、VALUES :array() UPDATE は、選択したレコード内の配列の列番号によって指定されたフィールド値を変更します。VALUES :array() の更新は、埋め込み SQL でのみ実行できます。この構文では、各値を DDL 列番号で指定する必要があります (列数には RowID 列 (列 1) を含めますが、この変更できないフィールドに値は指定しません)。MyStudents テーブルでは、4 歳以上 6 歳以下の児童には、‘P’ (‘Present (在籍)’ を示す) がその Q1Grade (列 5) および Q2Grade (列 6) のフィールドに指定されます。他のすべてのレコード・データは、変更されません。

  SET arry(5)="P"
  SET arry(6)="P"
  &sql(UPDATE SQLUser.MyStudents VALUES :arry() 
       WHERE FinalGrade='NA' AND StudentAge > 3)
  IF SQLCODE=0 {WRITE "Table Update successful",!
                WRITE "Rows updated=",%ROWCOUNT," Final RowID=",%ROWID }
  ELSE {WRITE "Table Update failed, SQLCODE=",SQLCODE,! }

関連項目

FeedbackOpens in a new tab