SQLコマンドの使用によるデータの更新

UPDATE文を使用して、表の行を更新できます。同じシャード・キーを共有する表内の複数の行の更新がサポートされるようになりました。シャード・キーを構成する表の列については、ここを参照してください。

  • Update文では、更新句を使用して、表内の1つ以上のフィールドの値を変更します。Oracle NoSQL Databaseでは、次の更新句がサポートされています:
    • SET句では、1つ以上の既存フィールドの値が更新されます。
    • ADD句では、1つ以上の配列に新しい要素が追加されます。
    • PUT句では、1つ以上のマップに新しいフィールドが追加されます。既存のマップ・フィールドの値を更新することもできます。
    • REMOVE句では、1つ以上の配列/マップから要素/フィールドを削除します。
    • JSON MERGE句では、JSONドキュメントに対して一連の変更を行うことができます。
    • SET TTL句では、行の有効期限が更新されます。
  • WHERE句では、どの行を更新するかを指定します。現在の実装では単一行の更新と複数行の更新の両方がサポートされるため、単一行の更新の場合はWHERE句で完全な主キーを指定し、複数行の更新の場合はシャード・キーを指定し、すべての行が同じシャードに存在するようにする必要があります。これにより、Oracle NoSQL DatabaseはACIDトランザクションでこの更新を実行できます。
  • オプションのRETURNING句は、SELECT句と同じように機能します。つまり、"*"を指定でき、その場合は更新された完全な行が返されます。または、返される必要があるものを指定する式のリストを指定できます。RETURNING句は、WHERE句に完全な主キーが含まれている場合にのみ機能します。

    ノート:

    現在、複数行の更新はサポートされていません。
  • さらに、WHERE条件を満たす行がない場合、UPDATE文は空の結果を返します。
  • また、1つの更新問合せで更新できるレコードの数にも制限があります。デフォルトでは、1つの更新問合せで最大1,000レコードを変更できます。これをオーバーライドするには、setLimit(int limit)メソッドを使用しますが、タイムアウトや待機時間の増加の原因となる可能性があるため、高く設定しすぎないようにしてください。詳細は、QueryRequest.setLimit(int limit)を参照してください。

例1: 列値を変更する単純な例。

UPDATE BaggageInfo 
SET contactPhone = "823-384-1964", 
confNo = "LE6J4Y" 
WHERE ticketNo = 1762344493810

説明: 前述の問合せは、SET句を使用して、特定のチケット番号のいくつかの列値を更新しています。

例 2: 行データを更新し、RETURNING句を使用して値をフェッチします。

UPDATE BaggageInfo 
SET contactPhone = "823-384-1964", 
confNo = "LE6J4Y"
WHERE ticketNo = 1762344493810 RETURNING *

説明: 前述の問合せでは、RETURNING句を使用して、UPDATEトランザクションの完了後にデータをフェッチしています。

出力:
{"ticketNo":1762344493810,"fullName":"Adam Phillips","gender":"M","contactPhone":"823-384-1964",
"confNo":"LE6J4Y",
"bagInfo":{"bagInfo":[{"bagArrivalDate":"2019.02.02 at 03:13:00 AEDT","flightLegs":
[{"actions":[{"actionAt":"MIA","actionCode":"ONLOAD to LAX","actionTime":"2019.02.01 at 01:13:00 EST"},
{"actionAt":"MIA","actionCode":"BagTag Scan at MIA","actionTime":"2019.02.01 at 00:47:00 EST"},
{"actionAt":"MIA","actionCode":"Checkin at MIA","actionTime":"2019.01.31 at 23:38:00 EST"}],
"estimatedArrival":"2019.02.01 at 03:00:00 PST","flightDate":"2019.02.01 at 01:00:00 EST",
"flightNo":"BM604","fltRouteDest":"LAX","fltRouteSrc":"MIA"},{"actions":
[{"actionAt":"MEL","actionCode":"Offload to Carousel at MEL","actionTime":"2019.02.02 at 03:15:00 AEDT"},
{"actionAt":"LAX","actionCode":"ONLOAD to MEL","actionTime":"2019.02.01 at 07:35:00 PST"},
{"actionAt":"LAX","actionCode":"OFFLOAD from LAX","actionTime":"2019.02.01 at 07:18:00 PST"}],
"estimatedArrival":"2019.02.02 at 03:15:00 AEDT","flightDate":"2019.01.31 at 22:13:00 PST",
"flightNo":"BM667","fltRouteDest":"MEL","fltRouteSrc":"LAX"}],"id":"79039899165297",
"lastActionCode":"OFFLOAD","lastActionDesc":"OFFLOAD","lastSeenStation":"MEL",
"lastSeenTimeGmt":"2019.02.02 at 03:13:00 AEDT","routing":"MIA/LAX/MEL","tagNum":"17657806255240"}]}}

例3: stream_acct表内の顧客のアカウント有効期限を更新します。

UPDATE stream_acct SET account_expiry="2023-12-28T00:00:00.0Z" WHERE acct_Id=3

説明: 前述の問合せでは、SET句を使用して、ストリーミング・メディア・アプリケーションの特定のアカウントのaccount_expiryフィールドを更新しています。

複数行の更新

EmployeeInfoという名前の表を作成し、IntegerのempID列(主キー)、Stringのdepartment列(シャード・キー)、StringのfullName列およびJSON型のinfo列を設定します。

CREATE TABLE EmployeeInfo (
    empID INTEGER,
    department STRING,
    fullName STRING,
    info JSON,
    PRIMARY KEY(SHARD(department), empID))

その後、次の行を追加します:

INSERT INTO EmployeeInfo VALUES (101, "HR", "Liam Phillips", {"salary":100000,"address":{"city":"Toronto","country":"Canada"}})
 
INSERT INTO EmployeeInfo VALUES (102, "HR", "Emma Johnson", {"salary":105000,"address":{"city":"Melbourne","country":"Australia"}})
 
INSERT INTO EmployeeInfo VALUES (103, "IT", "Carlos Martinez", {"salary":110000,"address":{"city":"Barcelona","country":"Spain"}})   
 
INSERT INTO EmployeeInfo VALUES (104, "Finance", "Sophia Becker", {"salary":130000,"address":{"city":"Munich","country":"Germany"}})

例1: UPDATE文を使用して複数の行を更新します。

次の文は、指定されたシャード・キーに関連付けられた行の指定されたフィールドを更新します。
UPDATE EmployeeInfo emp
    SET emp.info.address.city="Oslo",
    SET emp.info.address.country="Norway",
    SET emp.info.salary = emp.info.salary + 5000
 where department="HR"

説明: 前述の問合せでは、SET句によって、info.address.cityフィールドが「Oslo」、info.address.countryフィールドが「Norway」に更新され、シャード・キーとして指定されているdepartment列が「HR」と等しいすべての行のinfo.salaryフィールドが5000ずつ増分されます。このUPDATE文にはシャード・キーのみが記述されているため、データベースは更新された行数のみを返します。

出力:
+----------------+
 | NumRowsUpdated |
 +----------------+
 |              2 |
 +----------------+
1 row returned

ここで、SELECT問合せを実行して、更新された行を確認します。info.address.cityおよびinfo.address.countryフィールドがそれぞれ「Oslo」および「Norway」に更新されたことを確認し、HR部門で働くすべての従業員のinfo.salaryフィールドが5000ずつ増分されたことを確認します。

select * from EmployeeInfo
出力:
+-------+------------+-----------------+----------------------------+
 | empID | department |    fullName     |            info            |
 +-------+------------+-----------------+----------------------------+
 |   103 | IT         | Carlos Martinez | address                    |
 |       |            |                 |     city    | Barcelona    |
 |       |            |                 |     country | Spain        |
 |       |            |                 | salary      | 110000       |
 +-------+------------+-----------------+----------------------------+
 |   101 | HR         | Liam Phillips   | address                    |
 |       |            |                 |     city    | Oslo         |
 |       |            |                 |     country | Norway       |
 |       |            |                 | salary      | 105000       |
 +-------+------------+-----------------+----------------------------+
 |   102 | HR         | Emma Johnson    | address                    |
 |       |            |                 |     city    | Oslo         |
 |       |            |                 |     country | Norway       |
 |       |            |                 | salary      | 110000       |
 +-------+------------+-----------------+----------------------------+
 |   104 | Finance    | Sophia Becker   | address                    |
 |       |            |                 |     city    | Munich       |
 |       |            |                 |     country | Germany      |
 |       |            |                 | salary      | 130000       |
 +-------+------------+-----------------+----------------------------+
 
4 rows returned

例2: REURNING句を指定してUPDATE文を使用します

例2a: RETURNING句を使用して単一行を更新するには

UPDATE EmployeeInfo emp SET emp.info.salary = emp.info.salary + 1000 WHERE empID=101 and department="HR" RETURNING *

説明: 前述の問合せでは、SET句によって、HR部門の従業員IDが101の従業員の給与を1000増やし、その後にRETURNING句が続いています。WHERE句で完全な主キーが指定されているため、更新は1行に影響し、RETURNING句が存在するので出力が直接返されます。

出力:
+-------+------------+---------------+----------------------+
 | empID | department |   fullName    |         info         |
 +-------+------------+---------------+----------------------+
 |   101 | HR         | Liam Phillips | address              |
 |       |            |               |     city    | Oslo   |
 |       |            |               |     country | Norway |
 |       |            |               | salary      | 106000 |
 +-------+------------+---------------+----------------------+
 
1 row returned

例2b: RETURNING句を使用して複数の行を更新するには

UPDATE EmployeeInfo emp SET emp.info.salary = emp.info.salary + 1000 WHERE department="HR" RETURNING *

説明: 前述の問合せでは、SET句でHR部門の従業員の給与を1000ずつ増やすように指定し、その後にRETURNING句が続いています。HR部門には複数の従業員が在籍し、RETURNING句は複数行の更新では現在サポートされておらず、WHERE句で完全な主キーを指定する必要があるため、問合せによってエラーがスローされます。

出力:
Error handling command UPDATE EmployeeInfo emp SET emp.info.salary = emp.info.salary + 1000 WHERE department="HR" RETURNING *: Error: RETURNING clause is not supported unless the complete primary key is specified in the WHERE clause.

JSONデータの更新

例1:いくつかのフィールドを更新し、ネストされたJSONドキュメントを挿入して、bagInfo JSON配列から既存のドキュメントを削除します。

UPDATE BaggageInfo b 
JSON MERGE b.bagInfo[0].flightLegs[size(b.bagInfo[0].flightLegs)-1] WITH PATCH {"flightNo" : "BM107", "actions" : NULL, "tempActions" : {
        "actionAt" : "LAX",
        "actionStatus" : "in transit"
      }},
WHERE ticketNo = 1762344493810 RETURNING *

説明: 前述の問合せは、航空会社アプリケーションの乗客の手荷物追跡情報を更新しています。bagInfoフィールドは、乗客の手荷物追跡情報を格納するJSON配列です。JSON MERGEパッチを使用して、乗客の旅程の最後の区間の値を更新します。flightLegs JSON配列の最後の要素を計算するために、組込みのsize関数を使用しています。この関数は、移動セグメントの数を返し、それから1を減算しています。パッチ式で、更新するフィールドを指定します。ここでは、flightNo値を変更し、NULL値を指定してactionsフィールドを削除し、新しいJSONドキュメントtempActionsflightLegs JSON配列に挿入しています。

出力:
{
  "ticketNo" : 1762344493810,
  "fullName" : "Adam Phillips",
  "gender" : "M",
  "contactPhone" : "893-324-1064",
  "confNo" : "LE6J4Z",
  "bagInfo" : [{
    "bagArrivalDate" : "2019-02-01T16:13:00Z",
    "flightLegs" : [{
      "actions" : [{ ... }],
      "estimatedArrival" : "2019-02-01T11:00:00Z",
      "flightDate" : "2019-02-01T06:00:00Z",
      "flightNo" : "BM604",
      "fltRouteDest" : "LAX",
      "fltRouteSrc" : "MIA"
    }, {
      "estimatedArrival" : "2019-02-01T16:15:00Z",
      "flightDate" : "2019-02-01T06:13:00Z",
      "flightNo" : "BM107",
      "fltRouteDest" : "MEL",
      "fltRouteSrc" : "LAX",
      "tempActions" : {
        "actionAt" : "LAX",
        "actionStatus" : "in transit"
      }
    }],
    "id" : "79039899165297",
    "lastActionCode" : "OFFLOAD",
    "lastActionDesc" : "OFFLOAD",
    "lastSeenStation" : "MEL",
    "lastSeenTimeGmt" : "2019-02-01T16:13:00Z",
    "routing" : "MIA/LAX/MEL",
    "tagNum" : "17657806255240"
  }]
}

ノート:

ここで、bagInfoフィールドはJSONドキュメントの配列で、乗客ごとの受託手荷物を表します。更新する配列要素を指定しない場合、JSON MERGE句によって、bagInfo JSON配列全体がパッチの内容に置き換えられます。1人の乗客に複数の受託手荷物がある場合は、同じUPDATE文でJSON MERGE句を繰り返し使用できます。

例2: 更新文でJSON MERGEパッチおよびPUT句を使用します。

JSON MERGEパッチは、次のように単一のUPDATE文で他のすべての更新句(SET、ADD、PUT、REMOVE)とともに使用できます:
UPDATE BaggageInfo b 
JSON MERGE b.bagInfo[0].flightLegs WITH PATCH {"flightNo" : "BM107", "actions" : NULL, "tempActions" : {
        "actionAt" : "LAX",
        "actionStatus" : "in transit"
      }},
JSON MERGE b.bagInfo[1].flightLegs WITH PATCH {"flightNo" : "BM107", "actions" : NULL, "tempActions" : {
        "actionAt" : "LAX",
        "actionStatus" : "in transit"
      }},      
PUT b.bagInfo[0]{"bagArrivalDate" : "2019-03-13T00:00:00Z", "lastSeenStation" : "SFO", "routing" : "SFO/LAX",},
PUT b.bagInfo[1]{"bagArrivalDate" : "2019-03-13T00:00:00Z", "lastSeenStation" : "SFO", "routing" : "SFO/LAX",}
WHERE ticketNo = 1762320369957 RETURNING *

説明: 前述の問合せでは、乗客のレコードに2つの受託手荷物が含まれています。JSON MERGE句を繰り返し使用して、bagInfo JSON配列の両方の要素の手荷物追跡情報を更新しています。ターゲットのパス式には、flightLegs配列の個々の要素ではなく、flightLegsオブジェクトが含まれています。このため、パッチは、flightLegs JSON配列全体をflightLegs JSONオブジェクトに置き換えます。

PUT句は、bagInfo JSON配列の指定された要素内のbagArrivalDatelastSeenStationおよびroutingフィールドの値を更新しています。

出力:
{
  "ticketNo" : 1762320369957,
  "fullName" : "Lorenzo Phil",
  "gender" : "M",
  "contactPhone" : "364-610-4444",
  "confNo" : "QI3V6Z",
  "bagInfo" : [{
    "bagArrivalDate" : "2019-03-13T00:00:00Z",
    "flightLegs" : {
      "flightNo" : "BM107",
      "tempActions" : {
        "actionAt" : "LAX",
        "actionStatus" : "in transit"
      }
    },
    "id" : "79039899187755",
    "lastActionCode" : "OFFLOAD",
    "lastActionDesc" : "OFFLOAD",
    "lastSeenStation" : "SFO",
    "lastSeenTimeGmt" : "2019-03-12T15:05:00Z",
    "routing" : "SFO/LAX",
    "tagNum" : "17657806240001"
  }, {
    "bagArrivalDate" : "2019-03-13T00:00:00Z",
    "flightLegs" : {
      "flightNo" : "BM107",
      "tempActions" : {
        "actionAt" : "LAX",
        "actionStatus" : "in transit"
      }
    },
    "id" : "79039899197755",
    "lastActionCode" : "OFFLOAD",
    "lastActionDesc" : "OFFLOAD",
    "lastSeenStation" : "SFO",
    "lastSeenTimeGmt" : "2019-03-12T15:05:00Z",
    "routing" : "SFO/LAX",
    "tagNum" : "17657806340001"
  }]
}

JSONコレクション表の行の更新

ショッピング・アプリケーション表用に作成されたJSONコレクション表の行について考えてみます。

例:storeAcct表内の誤った買物客のデータ・レコードを変更します。

UPDATE文を使用して、JSONコレクション表の既存のドキュメントのフィールドを更新できます。UPDATE操作は、固定スキーマ表と同様に機能します。

{"contactPhone":"1617114988","address":{"Dropbox":"Presidency College","city":"Kansas City","state":"Alabama","zip":95065},"cart":[{"item":"A4 sheets","priceperunit":500,"quantity":2},{"item":"Mobile Holder","priceperunit":700,"quantity":1}],"email":"lorphil@usmail.com","firstName":"Lorenzo","lastName":"Phil","notify":"yes","orders":[{"EstDelivery":"2023-11-15","item":"AG Novels 1","orderID":"101200,"priceperunit":950,"status":"Preparing to dispatch"},{"EstDelivery":"2023-11-01","item":"Wall paper","orderID":"101200,"priceperunit":950,"status":"Transit"}]}
update句を使用して、買物客のデータを次のように修正します。
UPDATE storeAcct s
SET s.notify = "no",
REMOVE s.cart [$element.item = "A4 sheets"],
PUT s.address {"Block" : "C"},
SET s.orders[0].EstDelivery =  "2023-11-17",
ADD s.cart 1 {"item":"A3 sheets", "priceperunit":600, "quantity":2}
WHERE s.contactPhone = "1617114988"

説明:前述の例では、storeAcctテーブル内の買物客のレコードを更新して、不注意なエラーをいくつか修正しています。この修正には、storeAcct表の様々なフィールドの更新が必要です。SET句は、買物客のデータ・レコードの通知設定を非アクティブ化します。REMOVE句は、カート内のいずれかのitemフィールドがA4 sheetsと一致するかどうかをチェックし、対応する要素をorders配列から削除します。PUT句は、配信のランドマークを示す新しいJSONフィールドを追加します。2番目のSET句は、深くネストされたEstDeliveryフィールドにアクセスし、orders配列の最初の商品の推定配信日を更新します。ADD句は、cartフィールドに新しい要素を挿入して、追加商品の候補リストを作成します。

更新された買物客のデータをフェッチすると、次の出力が表示されます。

出力:
{"contactPhone":"1617114988","address":{"Block":"C","Dropbox":"Presidency College","city":"Kansas City","state":"Alabama","zip":95065},"cart":[{"item":"Mobile Holder","priceperunit":700,"quantity":1},{"item":"A3 sheets","priceperunit":600,"quantity":2}],"email":"lorphil@usmail.com","firstName":"Lorenzo","lastName":"Phil","notify":"no","orders":[{"EstDelivery":"2023-11-17","item":"AG Novels 1","orderID":"101200,"priceperunit":950,"status":"Preparing to dispatch"},{"EstDelivery":"2023-11-01","item":"Wall paper","orderID":"101200,"priceperunit":950,"status":"Transit"}]}