リファレンスガイド> データソースの機能サポート> データソースを組み合わせる際の関数サポートの問題> MERGE
 
MERGE
TDVは SQL 2003/2008 MERGE構文を使用します。データソースが MERGEをサポートしている場合、TDVは MERGEをプッシュします。
ターゲットテーブルのデータベースがJDBCドライバーでの配置された更新、挿入、および削除をサポートしている場合、フェデレーションマージが可能です。
MERGEとデータソース
次の表に、MERGEが関与する場合のデータソースとその処理を示します。
データソース
コメント
DB2 バージョン 8
ANSI MERGE 2003/2008をサポートします。 MERGEは可能な限りプッシュされます。ただし、非プッシュ(フェデレーション)の場合、ドライバーは完全なサポートに必要な機能の一部をサポートしていません。
MERGEステートメントにWHEN NOT MATCHED THEN INSERT句が含まれている場合、MERGEステートメントは失敗する可能性があります。新しいバージョンのDB2には、この問題はありません。
回避策は、MERGEステートメントを変更して完全にDB2にプッシュすることです。
DB2 バージョン 9.5、10.5、および z/OS
 
MySQL
MERGEをサポートしていません。ただし、REPLACE INTOとDUPLICATE KEYはあります。
MySQLデータのTDV MERGEを成功させるには、MySQLターゲットテーブルに主キーが必要であり、主キーのすべての列がMERGEの一部である必要があります。
同じMySQL接続からのテーブルのMERGEの場合:一方のResultSetが変更されると、ドライバーはもう一方のResultSetを閉じます。回避策は、データソースのコピーを作成して、同じデータソースに対して2つの異なるJDBC接続を使用するようにすることです。
Netezza
Netezzaは更新可能なカーソルをサポートしていないため、MERGEを実行することはできません。
Oracle
 
SQL Server 2008、2012
 
Sybase ASE
バージョン 15.7は、MERGEをサポートするASEの最初のバージョンです。
Sybase IQ
16までのバージョンはMERGEをサポートしていません。
Sybase用のJTDSドライバーは、更新可能な結果セットのスクロールをサポートしています。 JConnect7ドライバーはそうではありません。
Teradata
Teradata 12および13は、SQL 2003 MERGEをサポートしています。
Teradata 14はDELETEをサポートしていますが、WHEN句の検索条件はサポートしていません。
フェデレーションMERGEは、次のいずれかの条件下で可能になる場合があります。
ターゲットテーブルには、一意のインデックスの唯一のメンバーである列が含まれています。
列はテーブル上の1つ以上の一意のインデックスのメンバーであり、少なくとも1つの一意のインデックスのすべての列が結果セットで選択されています。
 
そのドライバーはスクロール可能なカーソルをサポートしていないため、フェデレーションMERGEをサポートしていません。
6.x
ANSI SQL 2003 MERGEをサポートします。
MERGEの例
このセクションには、いくつかの代表的なMERGEの例が含まれています。
この例では、サブクエリのIN句をテストします。
PROC ( : !DSMAP)
PROCEDURE m_mixed(out x CURSOR)
BEGIN
DECLARE guid VARCHAR(10) DEFAULT SUBSTRING('${ITEM_GUID}', 1, 10);
DELETE FROM /users/composite/test/sources/oracle/DEV1/UPDATES ;
INSERT INTO /users/composite/test/sources/oracle/DEV1/UPDATES (col_id,col_decimal, col_varchar) VALUES(3,30,guid),(4,40,guid),(5,50,guid),(6,60,guid),(-1,-10,guid);
MERGE INTO /users/composite/test/sources/oracle/DEV1/UPDATES
USING (SELECT * FROM /shared/examples/ds_inventory/tutorial/inventorytransactions) inventorytransactions
ON col_id = unitsreceived
WHEN MATCHED AND guid = col_varchar and col_decimal IN (SELECT o10_id * 10 FROM /users/composite/test/sources/oracle/DEV1/O10 WHERE o10_id IN (3,4)) THEN DELETE;
OPEN x FOR SELECT col_id,col_char,col_tinyint,col_smallint,col_decimal FROM /users/composite/test/sources/oracle/DEV1/UPDATES WHERE guid = col_varchar;
END
この例では、Microsoft SQL Serverをテストします。
PROC (SERIAL)
PROCEDURE m_pushed(out x CURSOR)
BEGIN
DECLARE guid VARCHAR(10) DEFAULT SUBSTRING('${ITEM_GUID}', 1, 6) || '019';
DELETE FROM /users/composite/test/sources/mssql_2k8/devstd/devstd/dbo/updates WHERE guid = c_varchar;
INSERT INTO /users/composite/test/sources/mssql_2k8/devstd/devstd/dbo/updates (c_id, c_decimal, c_varchar) values(3, null, guid), (4, 40, guid);
MERGE INTO /users/composite/test/sources/mssql_2k8/devstd/devstd/dbo/updates
USING /users/composite/test/sources/mssql_2k8/devstd/devstd/dbo/s10
ON c_id = S_id AND c_varchar = guid
WHEN MATCHED AND c_decimal + 1 IS NOT NULL THEN UPDATE SET c_id = S_id +10000 + c_id * 1000, c_char=S_char
;
OPEN x FOR SELECT c_id, c_decimal, c_char FROM /users/composite/test/sources/mssql_2k8/devstd/devstd/dbo/updates WHERE c_varchar = guid;
END
この例では、DB2をテストします。
PROC (DISABLED)
PROCEDURE m_mixed(out x CURSOR)
BEGIN
DELETE FROM /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES;
INSERT INTO /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES (c_id, c_decimal, c_varchar) values(3, null, '${ITEM_GUID}'), (4, 40, '${ITEM_GUID}');
MERGE INTO /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES
USING /users/composite/test/sources/mssql_2k8/devstd/devstd/dbo/s10
ON c_id = S_id and c_varchar = '${ITEM_GUID}'
WHEN NOT MATCHED THEN INSERT (c_id,c_char, c_varchar) VALUES (s_int, 'hey' || S_money, '${ITEM_GUID}');
OPEN x FOR SELECT c_id, c_char FROM /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES WHERE c_varchar = '${ITEM_GUID}';
END
MERGEステートメントでは、テーブルの同じ行をUPDATE、DELETE、およびINSERT操作の組み合わせのターゲットにすることはできません。これは、ターゲット行が複数のソース行と一致する場合に発生します。 ON句を調整して、ターゲット行が最大で1つのソース行と一致するようにするか、GROUPBY句を使用してソース行をグループ化します。
PROC
PROCEDURE m_pushed(out x CURSOR)
BEGIN
DECLARE guid VARCHAR(10) DEFAULT SUBSTRING('${ITEM_GUID}', 1, 10);
DELETE FROM /users/composite/test/sources/oracle/DEV1/UPDATES ;
INSERT INTO /users/composite/test/sources/oracle/DEV1/UPDATES (col_id,col_decimal, col_varchar) VALUES(3,30, guid);
MERGE INTO /users/composite/test/sources/oracle/DEV1/UPDATES
USING (SELECT * FROM /shared/examples/ds_inventory/tutorial/inventorytransactions) inventorytransactions
ON col_id = purchaseorderid
WHEN MATCHED AND col_varchar = guid THEN UPDATE SET col_tinyint=productid;
END
この例は、DB2が行を2回削除することを許可しないことをテストします。
PROC
PROCEDURE m_error(out x CURSOR)
BEGIN
DECLARE guid VARCHAR(10) DEFAULT SUBSTRING('${ITEM_GUID}', 1, 10);
DELETE FROM /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES;
INSERT INTO /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES (c_id, c_decimal, c_varchar) values(1, null, guid);
MERGE INTO /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES
USING (SELECT case WHEN "mixedCaseCol" in (1,2) THEN 1 ELSE "mixedCaseCol" end "mixedCaseCol"FROM /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/mixedCaseSchema/mixedCaseTable) mixedCaseTable
ON c_id = mixedCaseCol
WHEN MATCHED AND c_varchar = guid THEN DELETE
WHEN NOT MATCHED THEN INSERT (c_id, c_varchar, c_decimal) VALUES (3, guid, 50);
OPEN x FOR SELECT c_id, c_decimal FROM /users/composite/test/sources/"db2_9.5"/qa1_dev100_designbyexample/QA1/UPDATES WHERE guid = c_varchar;
END
このテストはNULLスキャンです。何も実行されるべきではありません。
PROC
PROCEDURE m_nullscan()
BEGIN
MERGE INTO /users/composite/test/sources/oracle/DEV1/UPDATES
USING /shared/examples/ds_inventory/tutorial/inventorytransactions
ON 1<>1
WHEN MATCHED THEN DELETE
;
END
このテストでは、JOINの左側が物理的な選択です。
PROC
PROCEDURE m_mixed_physical_selection()
BEGIN
MERGE
INTO /users/composite/test/sources/oracle/DEV1/UPDATES
USING /shared/examples/ds_inventory/tutorial/inventorytransactions
ON col_id = purchaseorderid AND col_char = pri_mp(781598358)
WHEN MATCHED THEN UPDATE SET col_tinyint=productid;
MERGE {option disable_push}
INTO /users/composite/test/sources/oracle/DEV1/UPDATES
USING /shared/examples/ds_inventory/tutorial/inventorytransactions
ON col_id = purchaseorderid AND col_char = pri_mp(781598358)
WHEN MATCHED THEN UPDATE SET col_tinyint=productid;
END
このテストは、MySQLがターゲットテーブルに、そのインデックスで選択されるすべての列に対して一意のインデックスを持っていることを要求していることを確認します。
PROC
PROCEDURE m_mixed()
BEGIN
MERGE INTO /users/composite/test/sources/mysql_v5/inventory/products
USING /users/composite/test/sources/mysql_v5/inventory/inventorytransactions
ON productname = transactiondescription
WHEN MATCHED THEN UPDATE SET categoryid = categoryid
;
END
次のSQLがSELECTステートメントを使用していた場合、論理プランジェネレーターはおそらく左側を削除します。 MERGEを使用すると、これが発生するのを防ぐことができます。
PROC
PROCEDURE m_outer_join_pruner()
BEGIN
MERGE
/users/composite/test/sources/mysql_v5/covoter/district USING
/users/composite/test/sources/mysql_v5/mysql/m10
ON
m10.m_id = district.oid
WHEN MATCHED THEN DELETE;
END
次のMERGEは、実際にはno-opスキャンです。一致する行はなく、WHEN NOTMATCHED句もありません。クエリエンジンは、それをno-opスキャン演算子に置き換える必要があります。
PROC
PROCEDURE null_scan()
BEGIN
MERGE INTO /users/composite/test/sources/oracle/DEV1/UPDATES u
USING /shared/examples/ds_inventory/tutorial/products p
ON 1 = 2
WHEN MATCHED THEN DELETE
;
END