前回のブログで、やじゅさんからODP側のバグじゃないかって話があがったので、一旦動作をまとめました。今回はODP.NETだけでなく、System.Data.OracleClientも含んでいます。
ちなみに、ODP.NETのマニュアルではExecuteNonQueryについて、次のように述べています。
XmlCommandType
およびCommandText
プロパティを使用してSQL文またはコマンドを実行し、影響を受ける行数を戻します
更新していなくても、更新していても、ExecuteNonQueryメソッドから「-1」が返ってきている時点でかなりアウトくさいです。つーかアウトですよね。影響を受けた行数が負ってどういうことじゃ!逆にこっちが影響受けた!?ソンナバカナ
DDLとコード
1. テーブル
CREATE TABLE MERGETABLE
(
KEY1 NUMBER(6,0),
COL1 VARCHAR2(50),
COL2 VARCHAR2(50),
OPTLOCK TIMESTAMP(9),
CONSTRAINT MERGETABLE_PK PRIMARY KEY (KEY1)
)
2. ソースコード
// Merge文
const string sql
= @"MERGE INTO MergeTable Target
USING (SELECT :key1 Key1, :col1 Col1, :col2 Col2, :optLock OptLock
FROM DUAL) InputSrc
ON (Target.Key1 = InputSrc.Key1)
WHEN MATCHED THEN
UPDATE SET
Col1 = InputSrc.Col1
, Col2 = InputSrc.Col2
WHERE Target.OptLock = InputSrc.OptLock
WHEN NOT MATCHED THEN
INSERT (Key1, Col1, Col2, OptLock)
VALUES (InputSrc.Key1, InputSrc.Col1, InputSrc.Col2, systimestamp)
";
// Merge文実行
private int ExecuteMergeSql()
{
using (OracleConnection conn = new OracleConnection("user id=xxx;password=yyy;data source=zzz"))
{
conn.Open();
OracleCommand command = conn.CreateCommand();
command.BindByName = true;
command.CommandText = sql;
command.Parameters.Add(new OracleParameter("key1", 2));
command.Parameters.Add(new OracleParameter("col1", "aaa"));
command.Parameters.Add(new OracleParameter("col2", "bbb"));
command.Parameters.Add(new OracleParameter("optLock", DateTime.Now));
int result = command.ExecuteNonQuery();
return result;
}
}
上記のソースコードはODP.NETのものです。System.Data.OracleClientを使用する場合は、BindByNameの一行をコメントアウトして下さい。
実行結果
クライアント |
サーバ |
結果 |
備考 |
System.Data.SqlClient |
SQLServer2008 |
○ |
|
System.Data.OracleClient |
OracleXE |
○ |
|
〃 |
Oracle11g |
○ |
|
ODP.NET(2.111.6.20) |
OracleXE |
× |
-1が返却される。 |
〃 |
Oracle11g |
× |
-1が返却される。 |
なんとSystem.Data.OracleClientは正しく動いている。というか、ODP.NETの独り負けのように見える…
何度かMerge文の記述方法を変えたりしましたが、全てアウト。ちょっと残念だー。
ほかの環境を試せたら良かったのですが、手元の環境ではこれが精一杯でした。とりあえずOracleに一報入れておきます。