1

MS Accessのクエリで、テキスト(文字列)値が空(または、実際にはnull)である可能性がある場所を防御的にクエリする必要があることを学びました(「指定されたキャストは無効です」例外を回避するにはどうすればよいですか? ) " IIF(ISNULL(colName),'',colName) " コンストラクトを使用して、次のようにします。

SELECT id, pack_size, IIF(ISNULL(description),'',description), department, subdepartment, IIF(ISNULL(vendor_id),'',vendor_id), IIF(ISNULL(vendor_item),'',vendor_item), avg_cost, list_cost FROM PhunkyPlatypi ORDER BY id

これは、required == false と指定された Text 列にのみ必要であると想定しています。私の ASSumption は間違っていますか? 必須ではないすべての列でこれを行う必要がありますか?

具体的には、データ型 double の列に関して防御的にクエリを実行する必要がある場合、これはその方法ですか?

IIF(ISNULL(two_bagger),0.0,two_bagger)

?

または、さらに良いこと (いつでも期待できます): すべての列にデータが含まれていない結果セットを処理するための、よりクリーンで邪魔にならない方法はありますか?

違いがある場合は、OleDbDataReader を使用して .NET 4.5.1 Web API アプリから MS Access データベースにクエリを実行しています (新しいワインスキンの古い泣き言?)

アップデート

Re: HansUp の (Reach for the Sky?) の提案: 「.Net 側からこれを攻撃し、コードをより Null に対応させる方が生産的になるかもしれません」より効率的/安全な方法があります:

if (null == oleDbD8aReader.GetString(2))
{
    description = "Blank description";
}
else
{
    description = oleDbD8aReader.GetString(2);
}

?

更新 2

DBNull をチェックするようにコードを変更し、DBNull の場合はデータ型 (Text の場合は string.empty、int の場合は 0、double の場合は 0.00) に基づいて値を一般的な値に設定しましたが、それでも同じエラー メッセージが表示されます。

更新 3

この行に「指定されたキャストが無効です」というメッセージが表示されます。

long RedemItemId = (oleDbD8aReader["dbp_id"] is DBNull ? 0 : (long)oleDbD8aReader["dbp_id"]);

dbp_id は Access テーブルの LongInt です

クエリから返されるデータには、その列に次の値が含まれます。

5
20
30
40
45
60
70
75
90
120
120

...では、これらの値のいずれかが long へのキャストに失敗している可能性はありますか? 「(long)」の代わりに「Convert.ToX()」を使用する必要がありますか? または...???

4

3 に答える 3

2

(クライアント側での処理に関する追加の質問への回答として...)

OleDbDataReaderは、Access データベースTextフィールドをSystem.String(値が含まれている場合) またはSystem.DBNull(Nullデータベース内にある場合) として返します。

DBNullしたがって、値を空 (長さゼロ) の文字列に変換したい場合は、

cmd.CommandText =
    "SELECT txtCol FROM Clients WHERE ID = 3";
OleDbDataReader rdr = cmd.ExecuteReader();
rdr.Read();
string result = rdr["txtCol"].toString();

返された値がそれをテストするかどうかを気にする場合DBNull

cmd.CommandText =
    "SELECT txtCol FROM Clients WHERE ID = 3";
OleDbDataReader rdr = cmd.ExecuteReader();
rdr.Read();
string result;
if (rdr["txtCol"] is DBNull)
{
    result = "{That field was Null.}";
}
else
{
    result = rdr["txtCol"].ToString();
}

(C# では、nullDBNull異なる生き物であることに注意してください。)

編集

同様に、数値データベース フィールド (たとえば、タイプDouble) の場合、次のように null を「強制」してゼロにすることができます。

cmd.CommandText =
    "SELECT dblCol FROM Clients WHERE ID = 3";
OleDbDataReader rdr = cmd.ExecuteReader();
rdr.Read();
double dResult = (rdr["dblCol"] is DBNull ? 0 : Convert.ToDouble(rdr["dblCol"]));
于 2013-10-25T19:35:52.003 に答える
2

「required == false と指定された Text 列の場合 ... すべての非必須列でこれを行う必要がありますか?」

多分。Required = True を設定していない場合、他のデータ型 (数値、日付/時刻など) の列には Null が含まれる可能性があります。また、LEFTorRIGHT JOINを使用すると、ソース テーブルのすべての列が Required = True であっても、一致しない行で Null を取得する可能性があります。クエリ出力に Null を使用したくない場合は、考えられるすべてのケースに対して置換を行う必要があります。

「データ型 double の列については、これがその方法ですか」

IIF(ISNULL(two_bagger),0.0,two_bagger)

はい、うまくいくはずです。または、必要に応じてこの方法で行うこともできます...

IIF(two_bagger Is Null,0.0,two_bagger)

OleDbから、「すべての列にデータが含まれていない結果セットを処理するための、よりクリーンで邪魔にならない方法」があるとは思いません。おそらく、これを.Net側面から攻撃し、コードをより Null に対応させる方が生産的でしょう...そうすれば、db エンジンに Null を別のものに置き換えるように依頼する必要がなくなります。

于 2013-10-25T16:16:22.257 に答える
0

非 SQL 非 Jet ですが、アクセス関数 NZ が役立ちます。

IIF(ISNULL(description),'',description)

ほぼ等しい

nz(description,'')

oleDbReader を介して利用可能かどうかを確認します

于 2013-10-25T17:51:30.513 に答える