MERGEのルールと制限事項 - Teradata Database - Teradata Vantage NewSQL Engine - ルールと制限事項、MERGE SQL文

Teradata Vantage™ SQLデータ操作言語

Product
Teradata Database
Teradata Vantage NewSQL Engine
Release Number
16.20
Published
2019年3月
Language
日本語
Last Update
2019-10-29
dita:mapPath
ja-JP/fbo1512081269404.ditamap
dita:ditavalPath
ja-JP/fbo1512081269404.ditaval
dita:id
B035-1146
Product Category
Software
Teradata Vantage

次のルールはMERGE文のさまざまな側面に適用されます。

単一行のMERGEのルールと制限

次の項目では、MERGEリクエストのソース テーブルのルールと制限に対する単一行の意味を定義します。
  • 指定のmatch_conditionには、ターゲット行の単一のプライマリ インデックスを指定しなければなりません。
  • source_table_referenceにサブクエリーを指定する場合、そのサブクエリーは単体のSELECTでなければならず(つまり、参照先のテーブルから複数の行を取得できない)、検索を行なうためにUPIまたはUSIのいずれかを指定しなければなりません。選択された列は、明示的に参照する必要があります。SELECT *構文は許可されていません。
  • source_table_referenceに列値の単純リストを指定する場合、検索は定義によって単一の行だけを検索します。

MERGEリクエストのON句のルール

MERGEリクエストON句には次のものがあります。
  • 単一(1つだけ)のプライマリ条件
  • ゼロ、1、または多数のセカンダリ条件

プライマリ条件は、MERGEリクエストを実行するために必要な条件であるのに対し、セカンダリ条件は、オプションで、アプリケーションが要求しない限り必要ありません。

次に、ON句のプライマリ条件とセカンダリ条件の例を示します。

次の2つのテーブルを作成し、その定義に従うMERGEリクエストを実行するとします。

     CREATE TABLE t1 (
       a1 INTEGER,
       b1 INTEGER,
       c1 INTEGER);
     CREATE TABLE t2 (
       a2 INTEGER,
       b2 INTEGER,
       c2 INTEGER);

     MERGE INTO t1
     USING t2
       ON a1=b2
     WHEN MATCHED THEN
       UPDATE SET b1=b2;

述部ON a1 = b2は、このMERGEリクエストの唯一のプライマリ条件です。

ON句をON a1=b2 AND c1=c2に変更すると、c1=c2がセカンダリ条件になります。

行パーティション テーブルのプライマリ条件の定義

行パーティション テーブルの場合、パーティション列セットがプライマリ条件の定義のコンポーネントでなければなりません。たとえば、次のターゲット テーブルとソース テーブルの定義でのMERGEリクエストについて考えてみましょう。

     CREATE TABLE t1 (
       a1 INTEGER,
       b1 INTEGER,
       c1 INTEGER)
     PRIMARY INDEX (a1)
     PARTITION BY (c1);

     CREATE TABLE t2 (
       a2 INTEGER,
       b2 INTEGER,
       c2 INTEGER);

     MERGE INTO t1
     USING t2
       ON a1=b2 AND c1=10 AND b1<b2
     WHEN MATCHED THEN
       UPDATE SET b1=b2;

このMERGEリクエストのプライマリ条件はa1=b2 AND c1=10で、b1<b2がセカンダリ条件です。

ON句の定義のルール

次のルールによって、このON句の定義を説明します。

ON句でのプライマリ条件のルール

ON句のプライマリ条件は等号制約でなければなりません。これは、有効なON句の述部に最小限必要な条件です。セカンダリ条件にはこの制限はありません。

例えば、次のMERGEリクエストは、ON句のプライマリ条件a1<a2が等号制約でないため、有効ではありません。

     MERGE INTO t1
     USING t2
       ON  a1<a2 
     WHEN MATCHED THEN
       UPDATE SET b1=b2;

次のMERGEリクエストは、ON句のプライマリ条件a1=a2が等号制約であるため有効です。セカンダリ条件b1<>b2は非等価ですが、Θ演算子はセカンダリ条件で有効なので、リクエストの妥当性に影響しません。

     USING t2
     MERGE INTO t1
       ON  a1=a2  AND b1<>b2
     WHEN MATCHED THEN
       UPDATE SET b1=b2;

ON句でのプライマリ条件の制限

ON句のプライマリ条件では、次の項目に対して式を指定できません。
  • ターゲット テーブルのプライマリ インデックス
  • ターゲット テーブルのパーティション式
  • ターゲット テーブルのプライマリ インデックスとパーティション式の両方

次のターゲット テーブルとソース テーブルの定義について考えてみましょう。

     CREATE TABLE t1 (
       a1 INTEGER,
       b1 INTEGER,
       c1 INTEGER)
     PRIMARY INDEX (a1)
     PARTITION BY (c1);

     CREATE TABLE t2 (
       a2 INTEGER,
       b2 INTEGER,
       c2 INTEGER);

次のMERGEリクエストは、ON句のプライマリ条件でターゲット テーブルt1のプライマリ インデックスa1とパーティション列c1に対してそれぞれ式a1+10c1*b1を指定しているので、有効ではありません。

     MERGE INTO t1
     USING t2
       ON  a1+10=b2 AND c1*b1=10  AND b1<b2
     WHEN MATCHED THEN
       UPDATE SET b1=b2;

ただし、プライマリ インデックスかパーティション列セット、またはその両方をセカンダリ条件で指定した場合、次の有効例に示すようにこの制限は適用されません。

     MERGE INTO t1
     USING t2
       ON a1=b2 AND c1=10 AND  a1+10=c2 AND c1*b1=10 
     WHEN MATCHED THEN
       UPDATE SET b1=b2;

このMERGEリクエストは、ONの条件式a1+10=c2c1*b1=10をセカンダリ条件で指定しているので、有効です。

ON句のプライマリ条件は等価条件である必要がある

ON句のプライマリ条件では、ターゲット テーブルのプライマリ インデックス、およびターゲット テーブルが行パーティション テーブルの場合はパーティション列を使用して、等価条件を指定する必要があります。式は、INSERT指定でプライマリ インデックスとパーティション化列に対して指定された式と同じでなければなりません。指定するプライマリ インデックスの値は、WHEN NOT MATCHED句のINSERT指定に指定された列値が暗黙に示すプライマリ インデックスの値(および、ターゲット テーブルが行パーティション テーブルの場合は、パーティション列の値)に一致する必要があります。

プライマリ インデックスの値が式の結果である

プライマリ インデックスの値が式を評価した結果の場合、その式はターゲット テーブルのどの列も参照できません。

次のターゲット テーブルとソース テーブルの定義について考えてみましょう。

     CREATE TABLE t1 (
       x1 INTEGER,
       y1 INTEGER,
       z1 INTEGER)
     PRIMARY INDEX(x1,y1);

     CREATE TABLE t2 (
       x2 INTEGER,
       y2 INTEGER,
       z2 INTEGER)
     PRIMARY INDEX(x2,y2);

次のMERGEリクエストは、ターゲット テーブルt1のプライマリ インデックス列x1とy1に対してそれぞれ等価条件を指定しているので、有効です。

     MERGE INTO t1
     USING t2
       ON  x1=z2 AND y1=y2 
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (z2, y2, x2);

次のMERGEリクエストは、ターゲット テーブルt1の各プライマリ インデックス列に対して等価条件を指定し、その条件のRHSに対する式y2+20z2+10もリクエストのINSERT指定でのt1のプライマリ インデックス列に対して指定されているので、有効です。

     MERGE INTO t1
     USING t2
       ON  x1=z2+10 AND y1=y2+20 
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (x1, y1, z1) VALUES (z2+10,  y2+20, x2);

行パーティション化されたターゲット テーブル

ターゲット テーブルが行パーティション テーブルの場合、MERGEリクエストのON句では、パーティション列に対する条件を指定する必要があり、そのWHEN NOT MATCHED句はその条件に一致する必要があります。

次のターゲット テーブルとソース テーブルの定義について考えてみましょう。

     CREATE TABLE t1 (
       x1 INTEGER,
       y1 INTEGER,
       z1 INTEGER)
     PRIMARY INDEX (x1)
     PARTITION BY y1;

     CREATE TABLE t2 (
       x2 INTEGER,
       y2 INTEGER,
       z2 INTEGER)
     PRIMARY INDEX (x2);

次のMERGEリクエストは、t1のパーティション列y1=y2に対して条件を指定し、INSERT指定によって値を列t2.y2からt1.y1に挿入するので、有効です。

     MERGE INTO t1
     USING (SELECT *
            FROM t2) AS s
       ON x1=x2 AND  y1=y2 
     WHEN MATCHED THEN
       UPDATE SET z1=z2
     WHEN NOT MATCHED THEN
       INSERT (x2,  y2, z2);

次のMERGEリクエストは有効ではありません。これは、ON句で有効な条件x1=z2 AND y1=y2を指定しながら、INSERT指定で列t2.y2の値を列t1.x1に挿入するためです。これは、ON句の条件に一致しません。

     MERGE INTO t1
     USING t2
       ON x1=z2 AND y1=y2
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (x1, y1, z1) VALUES (y2, z2, x2);

次のMERGEリクエストは有効ではありません。これは、ON句で有効な条件x1=z2+10を指定しながら、INSERT指定で式t2.y2 + 20の値をt1.x1に挿入するためです。これは、ON句の条件に一致しません。

     MERGE INTO t1
     USING t2
       ON  x1=z2+10  AND y1=y2+20
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (y2+20, z2+10, x2);

プライマリ条件はセカンダリ条件とAND付けされている必要がある

プライマリ条件は、ON句に指定するすべてのセカンダリ条件と論理積で結ぶ(AND付け)必要があります。セカンダリ条件の条件は、セカンダリ条件内で論理和で結ぶ(OR付け)ことができますが、プライマリ条件とOR付けすることはできません。

例えば、次のターゲット テーブルとソーステーブルの定義について考えてみましょう。

     CREATE TABLE t1 (
       a1 INTEGER,
       b1 INTEGER,
       c1 INTEGER);

     CREATE TABLE t2 (
       a2 INTEGER,
       b2 INTEGER,
       c2 INTEGER);

次のMERGEリクエストは、ターゲット テーブルのプライマリ インデックスの等価式a1=a2 (プライマリ条件)が、セカンダリ条件b1=b2とAND付けされているので、有効です。

     MERGE INTO t1
     USING t2
       ON a1=a2  AND  b1=b2
     WHEN MATCHED THEN
       UPDATE SET c1=c2;

次のMERGEリクエストは、ターゲット テーブルのプライマリ インデックスの等価式a1=a2がセカンダリ条件b1=b2とOR付けされているので、有効ではありません。

     MERGE INTO t1
     USING t2
       ON a1=a2  OR  b1=b2
     WHEN MATCHED THEN
       UPDATE SET c1=c2;

ただし、ON句のセカンダリ条件はOR付けされた条件を含むことができます。

例えば、次のMERGEリクエストは、プライマリ条件a1=a2がセカンダリ条件(b1=b2 OR c1=c2)とAND付けされ、論理和はセカンダリ条件内だけに含まれているので、有効です。

     MERGE INTO t1
     USING t2
       ON  a1=a2 AND (b1=b2 OR c1=c2) 
     WHEN MATCHED THEN
       UPDATE SET c1=c2;

MERGE ONの確定的関数および非確定的関数

MERGE文のON句で確定的関数と非確定的関数を指定する場合のルールは、プライマリ条件とセカンダリ条件で異なります。

この節では、ON句のプライマリ条件で確定的関数と非確定的関数を指定する場合の制限について説明します。

プライマリ条件でのMERGE ONの確定的関数

MERGE文のON句のプライマリ条件で確定的な関数を指定する場合の制限はありません。

例えば、次のMERGEリクエストは有効です。

     MERGE INTO t1
     USING t2
       ON a1=deterministic_udf(b2) AND b1=b2
     WHEN MATCHED THEN
       UPDATE SET c1=c2
     WHEN NOT MATCHED THEN
       INSERT (deterministic_udf(b2), a2, c2);

確定的UDF式deterministic_udf(b2)は、ソース テーブルt2をスプールしている間にソース テーブルの各行に対して1回だけ実行されます。INSERT指定を処理している間にこの式が再び実行されることはありません。ただし、ソース スプールで計算された値は、所定の場所で使用されます。これにより、パフォーマンスが最適化され、関数が複雑な場合はCPU時間が大幅に削減されます。

プライマリ条件でのMERGE ONの非確定的関数

ON句のプライマリ条件で非確定的関数を指定することはできません。ON句の式がINSERT指定のプライマリ インデックスの値に一致する場合でも、UDFがON句の文脈で実行されたときと、INSERT指定の文脈で実行されたときでは、UDFの結果が異なる可能性があり、不適切な挿入が実行される可能性があります。

この文脈では、不適切な挿入とは、非ローカルAMP挿入を引き起こす挿入操作です。つまり、行をターゲット テーブルに挿入する前に別のAMPに再分散する必要があります。

例えば、次のMERGEリクエストは、ON句のプライマリ条件として非確定的関数を指定しているので、その条件はINSERT指定に一致していますが、有効ではありません。

     MERGE INTO t1
     USING t2
       ON  a1=non_deterministic_udf(b2) 
     WHEN MATCHED THEN
       UPDATE SET b1=b2
     WHEN NOT MATCHED THEN
       INSERT (non_deterministic_udf(b2), a2, c2);

次の例は、ON句のプライマリ条件としてRANDOM関数を指定し、その条件はINSERT指定に一致していますが、非確定的関数であるため、このリクエストも有効ではありません。RANDOM関数の詳細について、<Teradata Vantage™ SQL関数、式、および述部、B035-1145>を参照してください。

     MERGE INTO t1
     USING t2
       ON  a1=RANDOM (1,100) 
     WHEN MATCHED THEN
       UPDATE SET b1=b2
     WHEN NOT MATCHED THEN
       INSERT (RANDOM (1,100), b2, c2);

この問題を回避するには、外部UDFを作成するときにCREATE FUNCTION文に適切なDETERMINISTICまたはNOT DETERMINISTICオプションを指定する必要があります。詳細については、<Teradata Vantage™ SQLデータ定義言語 - 詳細トピック、B035-1184>の「CREATE FUNCTION」と「CREATE FUNCTION(テーブル形式)」を参照してください。これは、構文解析プログラムがMERGEリクエストを適切に処理するために必要な処置を行なうのに役立ちます。外部UDFがDETERMINISTICとして指定された場合、その動作がNOT DETERMINISTICであっても、その実行によってリクエストの処理中に内部AMPエラーが発生し、リクエストがアボートされる可能性があります。

セカンダリ条件でのMERGE ONの確定的関数および非確定的関数

ON句のセカンダリ条件で確定的関数と非確定的関数を指定する場合の制限は、次のとおりです。

MERGEリクエストのON句のセカンダリ条件で確定的関数と非確定的関数を指定する場合の制限はありません。

例えば、次の事例では、ON句のセカンダリ条件としてdeterministic_udf関数とnon_deterministic_udf関数が指定されているので、これは有効なMERGEリクエストです。

     MERGE INTO t1
     USING t2
       ON a1=a2  AND b1=deterministic_udf(b2) 
                AND c1=non_deterministic_udf(c2) 
     WHEN MATCHED THEN
       UPDATE SET b1=b2
     WHEN NOT MATCHED THEN
       INSERT (a2, deterministic_udf(b2),
               non_deterministic_udf(c2));

RANDOM関数は、非確定的関数です。したがって、非確定的UDFに適用される制限がRANDOMにも適用されます。

次のMERGEリクエストは、ON句のセカンダリ条件にRANDOM関数を指定しているので、有効です。

     MERGE INTO t1
     USING t2
       ON a1=a2 AND  b1=RANDOM(1,100) 
     WHEN MATCHED THEN
       UPDATE SET b1=b2
     WHEN NOT MATCHED THEN
       INSERT (a2, RANDOM(1,100), c2);

ターゲット テーブルのプライマリ インデックスおよびパーティション列

ターゲット テーブルのプライマリ インデックスとパーティション列を更新する場合に、次のルールが適用されます。

ターゲット テーブルのプライマリ インデックスまたはパーティション列は更新できない。

次のターゲット テーブルとソース テーブルの定義について考えてみましょう。

     CREATE TABLE t1 (
       x1 INTEGER,
       y1 INTEGER,
       z1 INTEGER);

     CREATE TABLE t2 (
       x2 INTEGER,
       y2 INTEGER,
       z2 INTEGER)
     PRIMARY INDEX(x2)
     UNIQUE INDEX (y2);

次のMERGEリクエストは、そのWHERE句でUSI列y2に対して定数を指定することによってソース リレーションが単一行になるので、有効です。

     MERGE INTO t1
     USING (SELECT x2, y2, z2
            FROM t2
            WHERE y2=10) AS s
       ON  x1=10  AND y1=20
     WHEN MATCHED THEN
       UPDATE SET x1=10 
     WHEN NOT MATCHED THEN
       INSERT (y2, z2, x2);

次のMERGEリクエストは、ソース リレーションs(t2から派生)は単一行ですが、ON句で定数条件を指定しておらず(これは、ON句のルール2違反)、ターゲット テーブルt1、x1のプライマリ インデックスが更新されるので(これは、プライマリ インデックスとパーティション列の式に対する更新不可ルールに違反)、有効ではありません。

     MERGE INTO t1
     USING (SELECT x2, y2, z2
            FROM t2
            WHERE y2=10) AS s
       ON x1=y2 AND y1=z2
     WHEN MATCHED THEN
       UPDATE SET x1=10
     WHEN NOT MATCHED THEN
       INSERT (y2, z2, x2);

ターゲット テーブルのプライマリ インデックス

INSERT指定とON句の述部にターゲット テーブルのプライマリ インデックス(およびターゲット テーブルが行パーティション テーブルの場合は、そのパーティション列)に対する等価条件を指定し、式にソース テーブルの列だけを指定する場合は、ターゲット テーブルのプライマリ インデックスは識別列になることができません。

このルールには次の例外があります。
  • ソース関係が有効な単一行subqueryの場合
  • リクエストにINSERT指定を指定せず、ON句のプライマリ条件が等価制約である場合
  • MERGEリクエストにターゲット テーブルのプライマリ インデックス(および、ターゲット テーブルが行パーティション テーブルの場合はパーティション列セット)に対する等価条件がある場合に、INSERT句を指定しない場合

3つの有効な例については、例: MERGEおよび識別列を参照してください。

次のターゲット テーブルとソース テーブルの定義について考えてみましょう。ターゲット テーブルt1は、そのデフォルトのプライマリ インデックスで識別列x1を定義しています。

     CREATE TABLE t1 (
       x1 INTEGER GENERATED BY DEFAULT AS IDENTITY,
       y1 INTEGER,
       z1 INTEGER);

     CREATE TABLE t2 (x2 INT,
       y2 INTEGER,
       z2 INTEGER)
     PRIMARY INDEX (x2)
     UNIQUE INDEX (y2);

次のMERGEリクエストは有効です。これは、t2の射影を基にしたソース リレーションsが有効な単一行のサブクエリーだからです。

     MERGE INTO t1
     USING (SELECT x2, y2, z2
            FROM t2
            WHERE y2=10) AS s
       ON x1=10 AND y1=20
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (y2, z2, x2);

次のMERGEリクエストで定数を指定しない場合、WHEN NOT MATCHED句が指定されていない場合にはON句のルール1に従う必要があります。この場合、リクエストは無効になります。ただし、この例ではWHEN MATCHED句に定数値10を指定しているので、有効です。

     MERGE INTO t1
     USING (SELECT x2, y2, z2
            FROM t2
            WHERE y2=10) AS s
       ON x1=y2 AND y1=z2
     WHEN MATCHED THEN
       UPDATE SET  z1=10;

MERGEの列はソース テーブルまたはターゲット テーブルを参照する必要がある

MERGEリクエストのON、WHEN MATCHED、WHEN NOT MATCHED句には、ソース テーブルまたはターゲット テーブルを参照する列をのみを指定できます。

次のMERGEリクエストは、ON句で列t4.x4を参照し、その列は、リクエストのソース テーブルにもターゲット テーブルにもないので、有効ではありません。

     MERGE INTO t1
     USING (SELECT x2, y2, z3
            FROM t2, t3
            WHERE y2=10) AS s
       ON x1=y2 AND  t4.x4=z2
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (y2, z2, x2);

次のMERGEリクエストは、ON句でテーブルと列t3.x4を参照し、その列は、リクエストのソースでもターゲットでもないので、有効ではありません。

     MERGE INTO t1
     USING (SELECT x2, y2, z3
            FROM t2, t3
            WHERE y2=10) AS s
       ON x1=y2 AND  t3.x4=z2
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (y2, z2, x2);

ON句の条件

ON句の条件には、結合条件と同じ制限があり、さらにON句には、サブクエリーを指定できないという制限があります。

次のMERGEリクエストは、ON句にサブクエリーを指定しているので有効ではありません。

     MERGE INTO t1
     USING t2
       ON a1=a2 AND c1 IN  (SELECT b2 
                           FROM   t2) 
     WHEN MATCHED THEN
       UPDATE SET c1=c2+2;

次のMERGEリクエストは、ON句に集約演算子SUMを指定しているので有効ではありません。

     MERGE INTO t1
     USING t2
       ON a1=a2 AND  SUM(b1)=10 
     WHEN NOT MATCHED THEN
       INSERT (a2,b2,c2);

MERGE文でのソース テーブルのルール

ソース リレーションがサブクエリーによって定義される場合、そのサブクエリーは、派生テーブルの制限に準拠する必要があります。派生テーブルのルールと制限を参照してください。次のSQL文はどれも指定できません。
  • ORDER BY
  • recursion
  • WITH
  • WITH … BY

次のMERGEリクエストは、ソース リレーションのサブクエリーにWITH ... BY句を指定しているので有効ではありません。

     MERGE INTO t1
     USING (SELECT a2, b2, c2
            FROM t2
            WITH SUM(b2) BY c2) AS source (a2, b2, c2)
       ON a1=a2
     WHEN MATCHED THEN
       UPDATE SET c1=c2;

次のMERGEリクエストは、ソース リレーションのサブクエリーにORDER BY句を指定しているので有効ではありません。

     MERGE INTO t1
     USING (SELECT a2, b2, c2
            FROM t2
            ORDER BY b2) AS source (a2, b2, c2)
       ON a1=a2
     WHEN NOT MATCHED THEN
       INSERT (a2,b2,c2);

サブクエリーを使用してソース テーブルを指定する場合、そのサブクエリーの選択リストは、そのサブクエリーによって作成される派生テーブルの列を参照できません。

UPDATEソース テーブルに、ターゲット テーブルの特定の行に一致する行が複数存在する場合、エラーが発生します。

例えば、次のターゲット テーブルとソース テーブルを定義するとします。

     CREATE TABLE target (
       a INTEGER,
       b INTEGER);

     CREATE TABLE source (
       c INTEGER,
       d INTEGER);

次のINSERTリクエストを使用してテーブルに入力します。

     INSERT INTO target VALUES (1,1);

     INSERT INTO source VALUES (1,2);

     INSERT INTO source VALUES (1,3);

次のMERGEリクエストを実行します。

     MERGE INTO target AS t
     USING (SELECT c, d
            FROM source) AS s
       ON t.a=s.c
     WHEN MATCHED THEN
       UPDATE SET b=s.d;

ターゲット テーブルは、更新前は次のようなテーブルであると仮定します。列dの値の順序は、ソース テーブルのバージョン1とバージョン2で異なります。

source - version 1   target
c d   a b
1 2   1 1
1 3      
source - version 2  
c d
1 3
1 2

このMERGE更新操作の結果は、ソースの行の順序によって異なります。例えば、バージョン1のソースを使用してターゲットを更新した結果と、バージョン2のソースを使用してターゲットを更新した結果を比較します。

バージョン1を使用:

target  
a b
1 2

バージョン2を使用:

target  
a b
1 3

ご覧のように、ソースの行の順序に応じて、ターゲットの列bの最終的な値は、2または3になります。これは、非確定的な動作を証明しています。

これはエラー状態です。

このエラーを回避するには、ソース テーブルの複数の一致する行を1つの行にまとめておく必要があります。例えば、GROUP BY句を使用して複数の行を集約してsource_table_name参照に列値を追加しておくことができます。

ソース リレーションが単一行であることが保証されている(つまり、明示的な値リストを指定しているか、UPIまたはUSI制約を指定した単一テーブルのsubqueryである)と、ON句の述部には、プライマリ インデックスと定数値、およびパーティション列セット(ターゲットが行パーティション テーブルである場合)と定数値の間に等価条件を持つことができます。

INSERT指定は、ON句の等価条件で指定された定数に一致しても一致しなくてもかまいません。

USING subqueryで、固有インデックスに等価条件を指定することによって単一行ソース リレーションが保証される場合、subqueryにパーティション列セットを指定する必要はありません。例: 単一行ソース リレーションが保証される場合、パーティション列セットを指定する必要がないを参照してください。

MERGE文でのターゲット テーブルのルール

MERGE文でのターゲット テーブルのルールを以下に示します。

MERGE文の実行開始前に存在したターゲット テーブルの行だけが、更新の候補となります。MERGEリクエストの実行開始後にターゲット テーブルに挿入された行は、MERGEリクエストの実行が停止するまで更新できません。

MERGE操作のターゲット リレーションは、次のいずれかの種類のリレーションにすることができます。
  • 基本データ テーブル
  • グローバル一時テーブル
  • ハッシュ テーブル
  • キュー テーブル
  • 更新可能(単一テーブル)ビュー
  • 揮発テーブル

MERGE操作のターゲット リレーションは、結合テーブル(更新できない)ビューにすることができません。例えば、MERGE操作のターゲット リレーションとして、次のようなビューを指定することはできません。

     CREATE VIEW v (a, b, c) AS
       SELECT a2, b2, c2
       FROM t2 INNER JOIN t1 ON a1=a2;
MERGE操作のターゲット リレーションは、次の種類のリレーションにすることができません。
  • 派生テーブル
  • グローバル一時トレース テーブル
  • ハッシュ インデックス
  • 結合テーブル(更新できない)ビュー
  • 結合インデックス
  • ジャーナル テーブル

ターゲット テーブルが行パーティション テーブルの場合、ON条件のパーティション列セットの代わりに、システム派生PARTITION列とシステム派生PARTITION#L n列を使用することはできません。

ON句の述部のセカンダリ条件として、システム派生PARTITION列を代入できます。

MERGE操作のターゲット テーブルには、識別列を入れることができます。<Teradata Vantage™ SQLデータ定義言語 - 詳細トピック、B035-1184>の「識別列」を参照してください。システムは、識別列のないテーブルに単体の挿入を行なうときと同様の方法で、いくつかのMERGE挿入を識別列の中に生成します。

ただし、ほとんどの状況では、識別列をターゲット テーブルのプライマリ インデックスにすることはできません。プライマリ インデックスの識別列に適用されるルールと例外については、ターゲット テーブルのプライマリ インデックスを参照してください。

WHEN NOT MATCHED THEN句のINSERT指定にターゲット テーブルの列を指定することはできません。

MERGEのWHEN MATCHEDおよびWHEN NOT MATCHEDのルール

MERGEリクエストでは、最大で1つのWHEN MATCHED句と最大で1つのWHEN NOT MATCHED句を指定できます。

MERGEリクエストでWHEN MATCHED句とWHEN NOT MATCHED句を指定した場合、その句のINSERT指定とUPDATE指定は同じAMPに適用する必要があります。

INSERT指定のプライマリ インデックスに指定する値は、ON句に指定されたターゲット テーブルのプライマリ インデックスに一致する必要があります。

WHEN MATCHED句が指定されたMERGE文の場合、ターゲット テーブルの更新されるすべての列に対するUPDATE権限またはターゲット テーブルから削除されるすべての列に対するDELETE権限が必要です。

また、MERGEリクエストの条件および割当ての右側で参照される列に対するSELECT権限も必要です。

MERGEリクエストのUPDATE指定には、UPDATEリクエストと同じ制限があります。UPDATEを参照してください。

WHEN MATCHED句のmatch_conditionは、ターゲット テーブルのプライマリ インデックスを完全に指定する必要があります。

WHEN NOT MATCHED句を使用するには、ユーザーにターゲット テーブルの列ごとにINSERT権限が必要です。また、MERGEリクエストの条件および割当ての右側で参照される列に対するSELECT権限も必要です。

MERGEリクエストのINSERT指定には、INSERTリクエストと同じ制限があります。ただし、テーブルがMULTISETとして定義され、リクエストがANSIセッション モードで実行されている場合でも、重複行をテーブルに挿入できません。INSERT/INSERT … SELECTを参照してください。

WHEN MATCHED句またはWHEN NOT MATCHED句で、ソース テーブルでもターゲット テーブルでもないテーブルを参照する列を指定することはできません。

ターゲット テーブルの列は、WHEN NOT MATCHED THEN句のINSERT指定の値として指定できません。行はソース テーブルから挿入する必要があり、ソース テーブルとターゲット テーブルの行の混合としてINSERTマージ行は存在できません。次のリクエストは、INSERT指定にターゲット テーブルの列z1があるので有効ではありません。

     MERGE INTO t1
     USING (SELECT x2, y2, z3
            FROM t2, t3
            WHERE y2=10) AS s
       ON x1=y2 AND t4.x4=z2
     WHEN MATCHED THEN
       UPDATE SET z1=10
     WHEN NOT MATCHED THEN
       INSERT (x1, y1,  z1) VALUES (y2,  t1.z1, x2);

DELETEを指定したMERGE文のルール

DELETE句を指定したMERGE-INTO文は、条件が真と評価されたターゲット テーブルの行を削除します。USINGキーワードに続くsource_table_nameは、削除対象のターゲット テーブルを指定します。

WHEN MATCHED THENにはUPDATEまたはDELETEを含めることができますが、両方を含めることはできません。

DELETEを指定した場合は、INSERTは指定できません。

DELETE句が指定されており、DELETEトリガーがターゲット オブジェクトに定義されている場合、MERGE-INTO文はDELETEトリガーのトリガー起動イベントとして機能できます。

埋め込みSQLアプリケーションでMERGEリクエストを使用するときのルール

埋め込みSQLアプリケーション プログラムにMERGEリクエストを埋め込んで、対話式にそのリクエストを実行するか、動的に準備して、そのリクエストを実行できます。

USING subquery句のWHERE句(ただし選択リストでは不可)、match_conditionupdate_expressionおよびinsert_expressionにホスト変数を指定できます。

すべてのホスト変数はコロン文字で始まらなければなりません。

MERGEリクエストのその他のルール

MERGEリクエストでDEFAULT関数を使用するときのルール

MERGEリクエストでDEFAULT関数を使用する場合、以下のルールが適用されます。
  • DEFAULT関数は、リレーション列を名前で識別する単一の引数を取ります。この関数は、列の現行デフォルト値に等しい値と評価されます。列のデフォルト値が現行のビルトイン システム関数として指定される場合、DEFAULT関数は、リクエストの実行時にシステム変数の現行値と評価されます。

    この結果として、DEFAULT関数のデータ型は、デフォルトがヌルでない場合、デフォルトとして指定される定数またはビルトイン関数のデータ型になります。デフォルトがヌルの場合、DEFAULT関数のデータ型は、デフォルトのリクエスト対象である列または式のデータ型と同じになります。

  • DEFAULT関数は、DEFAULTまたはDEFAULT (column_name)として指定できます。列名が指定されていない場合、システムは列を文脈に基づいて派生させます。列のコンテキストを派生させることができない場合、リクエストはアボートし、エラーが要求元に戻されます。
  • UPDATE文用にリストされたすべてのルールも、MERGE文のUPDATEに適用されます。UPDATEでのDEFAULT関数の使用上のルールを参照してください。
  • INSERT文用にリストされたすべてのルールも、MERGE文のINSERTに適用されます。DEFAULT関数を使用した挿入を参照してください。
  • SQLフラッガーがオンになっている場合、挿入または更新のために列名の引数が指定されているDEFAULT関数はTeradataの拡張機能としてフラグが付けられます。

DEFAULT関数の詳細について、<Teradata Vantage™ SQL関数、式、および述部、B035-1145>を参照してください。

MERGEを行パーティション テーブルで使用するためのルール

MERGE文を使用して行パーティション プライマリ インデックス テーブルに行を挿入したり、パーティション式の列を更新する際には、以下のルールが適用されます。
  • ターゲット テーブルは行パーティション化できます。ただし、ターゲット テーブルは列パーティション化できません。
  • テーブルのパーティション列を更新するMERGEリクエストの場合、パーティション式の結果は1とそのレベルに定義されたパーティション数の間の値になる必要があります。
  • テーブルに行を挿入するMERGEリクエストの場合、その行のパーティション式の結果は1とそのレベルに定義されたパーティション数の間の値になる必要があります。
  • パーティション式の一部としてPeriod列を指定すると、MERGEリクエストのそのPeriod列には、等価条件のみを指定できます。テーブルのパーティション式に含まれているPeriod列に対して不等条件を指定するMERGEリクエストは、エラーを返します。

    MERGEリクエストのその列に対する等価条件と不等条件の両方に、パーティション式の一部としては定義されていないPeriod列を指定できます。

  • パーティション式で期間値BEGINまたはENDを参照する関数を指定すると、その関数の等価条件はパーティション値マッチング条件として処理されます。

    パーティション式で期間BEGINとENDの両方を参照する関数を指定すると、BEGINとENDに対する等価条件がパーティション マッチング条件として処理されます。

    そうしたリクエストは、単一パーティションになる必要があります。

  • 条件IS UNTIL_CHANGEDおよびIS UNTIL_CLOSEDが、END期間のみを参照する関数に対する等価条件として処理されます。<Teradata Vantage™ ANSIテンポラル テーブル サポート、B035-1186>および<Teradata Vantage™ テンポラル テーブル サポート、B035-1182>を参照してください。
  • INSERT句はマッチング条件と同じパーティション列値を指定する必要があります。

    このルールは、マッチング条件が期間を参照する関数を指定する際にも適用されます。

  • システム派生列PARTITIONおよびPARTITION#L1~PARTITION#L62を更新できません。
  • システム派生PARTITION列に値およびnullを挿入できません。
  • パーティション式の評価中に、エラー(ゼロで割るなど)が発生することがあります。システムは、エラー発生時に実行されているセッション モードに応じてそのエラーに応答します。
セッション モード 式評価エラーに応じてロールバックされる作業単位
ANSI エラーを含むリクエスト。
Teradata エラーを含むトランザクション。
式のエラーを防ぐために、パーティション式の設計時には注意が必要です。
  • マージ操作の成功のために、テーブルが作成された時点のセッション モードおよびセッション照合が、現在のセッション モードおよび照合と一致する必要はありません。行挿入先または更新先の行パーティションは、テーブルのセッション モードと照合を使用してパーティション列値のパーティション式を評価することによって決まるからです。
  • 文字のパーティションで定義されたテーブルへの行のマージについて、照合は次の影響を及ぼします。テーブルの照合がMULTINATIONALかCHARSET_COLLのいずれかで、テーブルが作成されてから照合の定義に変更があった場合、システムはテーブルへの行のマージを試みるリクエストをアボートし、要求元にエラーを返します。
  • テーブル結合インデックスのパーティション式が、Unicode文字式またはリテラルを伴い、テーブルまたは結合インデックスが定義されたときに有効だったコード ポイントとは一致しないUnicodeコード ポイントを持つリリースにまでシステムが戻されると、Teradata Databaseはテーブルへの行挿入の試みをアボートし、要求元にエラーを返します。

行パーティション結合インデックスを持つテーブルでMERGEを使用するためのルール

行パーティション結合インデックスを持つテーブルでMERGEを使用するためのルールは、以下のとおりです。
  • 基本テーブルの行を挿入または更新するMERGEリクエストで、行パーティションを使用する結合インデックスにインデックス行が挿入される結果となる場合、そのインデックス行のパーティション式の結果は1とそのレベルに定義されたパーティション数の間の値になる必要があります。
  • 基本テーブルの行を挿入または更新するMERGEリクエストで、行パーティションを使用する結合インデックスのインデックス行が更新される結果となる場合、更新後のインデックス行のパーティション式の結果は1とそのレベルに定義されたパーティション数の間の値になる必要があります。
  • 基本テーブルに行をマージすると、必ずその基本テーブルで結合インデックスへの挿入または更新が起きるわけではありません。

    例えば、CREATE JOIN INDEX文でWHERE句を指定して、WHERE句の条件に一致する行だけがインデックスに挿入されるスパース結合インデックスを作成できます。結合インデックスの行が更新され、更新後にWHERE句の条件に一致しなくなる場合は、その行はインデックスから削除されます。

    このアクティビティのプロセスは次のとおりです。
    1. 行への更新が行なわれた後、Teradata DatabaseはWHERE句の条件がtrueの値になるかどうかをチェックします。
      条件の評価 システムの実行内容
      FALSE スパース結合インデックスから行を削除します。
      TRUE スパース結合インデックスで行を維持し、段階bに進みます。
    2. Teradata Databaseは、更新された行のパーティション式の新しい結果を評価します。
      パーティション式の評価 Result
      Nullであり、適切なNO RANGEおよびUNKNOWNオプションが指定されていない場合。 リクエストはエラーを返し、基本テーブルまたはスパース結合インデックスのいずれかを更新しません。
      Nullであり、適切なNO RANGEおよびUNKNOWNオプションが指定されている場合。 行をスパース結合インデックスのNO RANGEまたはUNKNOWNパーティションに格納し、リクエストの処理を続行します。
      値。 適切なパーティションに行を格納し、リクエストの処理を続行します。そのパーティションは、以前行が格納されたパーティションと異なる場合があります。
  • 文字パーティションで定義されたテーブルへの行のマージについて、照合は次の影響を及ぼします。

    テーブルに、照合順序がMULTINATIONALまたはCHARSET_COLLのいずれかの、文字パーティションを使った非圧縮結合インデックスが定義されていて、結合インデックスが作成されてから照合の定義に変更があった場合、マージによって結合インデックスで行が変更されたかどうかに関係なく、テーブルへの行のマージを試みるリクエストはエラーを返します。

    非圧縮結合インデックスのパーティション式が、Unicode文字式またはリテラルを伴い、テーブルまたは結合インデックスが定義されたときに有効だったコード ポイントとは一致しないUnicodeコード ポイントを持つリリースにまでシステムが戻されると、テーブルへの行挿入の試みはエラーを返します。

MERGEリクエストからのスカラーUDFの呼び出しに関するルール

MERGEリクエストの次の句から、スカラーUDFを呼び出すことができます。
  • SELECT

    MERGEリクエストのUSING SELECT句から、スカラーUDFを呼び出すことができます。

    別名を持つスカラーUDF呼び出しの結果を参照するには、別名を使用する必要があります。

  • ON

    MERGEリクエストのON句から、指定された検索条件内の式内で呼び出す場合にはセカンダリ条件として、または、プライマリ インデックスにバインドされている場合にはプライマリ条件として、スカラーUDFを呼び出すことができます。

    SELECTリクエストのON句に適用できるその他のルールは、MERGEリクエストのON句にも適用できます。SELECT結合式を参照してください。

  • UPDATE … SET

    UDFが常に値式を返す限り、UPDATEリクエストのSET句の右辺でスカラーUDFを呼び出すことができます。

  • INSERT … VALUES

    MERGEリクエストのINSERT指定のVALUES句から、スカラーUDFを呼び出すことができます。

    INSERT指定のVALUES句内でスカラーUDFを指定する際のルールは、次のとおりです。
    • スカラーUDFに渡される引数は、次のカテゴリに制限されています。
      • 定数
      • 定数を解決するパラメータ
      • USING値
    • スカラーUDFは、常に値式を返す必要があります。

MERGE挿入操作、MERGE更新操作、およびUDT

UDT列への挿入に関するルールについては、UDT列への挿入を参照してください。

MERGEリクエストを使ったスカラー サブクエリーを使用するためのルール

MERGEリクエストにスカラー サブクエリーを指定することはできません。

行レベル セキュリティ制約で保護されるテーブルにおけるMERGEの使用ルール

MERGEリクエストは、以下について使用できます。
  • 行レベル セキュリティ制約のあるテーブルの更新(テーブルが同じ行レベル セキュリティ制約で定義されている場合)
  • ターゲット テーブルへの行の挿入

キュー テーブルとMERGEのルール

MERGEリクエストでキュー テーブルを指定する場合、以下の制限が適用されます。
  • SELECT AND CONSUMEリクエストを含む複文リクエストの中で、それと同じキュー テーブルに対するMERGE文を指定することはできません。
  • MERGEリクエストのUSING句で、サブクエリーとしてSELECT AND CONSUMEリクエストを指定することはできません。

トリガーするアクションとしてのMERGE

subqueryが行を戻さない場合、トリガーは起動されません。

トリガーがMERGEリクエストの結果として起動される場合、以下の動作が生じます。

トリガーが定義されているアクションのタイプ トリガーを起動する句 match_condition結果
UPDATE WHEN MATCHED THEN 満たされる場合のみ
DELETE WHEN MATCHED THEN 満たされる場合のみ
INSERT WHEN NOT MATCHED THEN 満たされない場合のみ

トリガーされるアクションとしてのMERGE

MERGEはトリガーされるアクションとしてサポートされていません。

ロード分離テーブルに対するMERGEサポート

ロード分離テーブルでの非同時ロード分離マージ削除操作により、一致した行が物理的に削除されます。ロード分離テーブルでの非同時分離マージ更新操作により、一致した行がその場で更新されます。

ロード分離テーブルでの同時ロード分離マージ削除操作により、一致した行が論理的に削除されます。ロード分離テーブルでの同時ロード分離マージ更新操作により、一致した行が論理的に削除され、値が変更された行が挿入されます。行は削除済みとマーク付けされ、スペースは、ALTER TABLE文にRELEASE DELETED ROWSオプションを指定して発行するまで再利用されません。<Teradata Vantage™ SQLデータ定義言語 - 構文規則および例、B035-1144>を参照してください。