プロが教える店舗&オフィスのセキュリティ対策術

Accessで作ったクエリで表示されるデータと、VBAでSQLを組んでそのクエリから抽出したデータが異なるので困っています。

ちょっと言葉では説明しにくいので表で説明します。

元となるテーブル(t_test)がたとえば以下のようになっているとします。

t_test
顧客id  商品id
1      A-1
2      A-2
3      B-1
4      A-1

これを元に、以下のようなクエリ(q_test)を作ります。

q_test
顧客id  商品id  式1: IIf([商品id] Like "A*",1,0)
1      A-1    1
2      A-2    1
3      B-1    0
4      A-1    1

VBAで以下のようなSQLを実行すると、なぜか式1の値が全て0となります。

sql = "SELECT * FROM q_test"
1      A-1    0
2      A-2    0
3      B-1    0
4      A-1    0

式1でLIKEを使っていることが原因なのか、
IIf([商品id] = "A-1",1,0)
とかだと、クエリとSQLの結果に違いはありません。
IIfだけでなくSwitchを使った場合も同様(LIKEだとおかしい、=だと平気)でした。

ちなみに、Accessのバージョンは2003、VBAで使っているレコードセットはADODBです。
(今確認したところ、DAOでは問題なくできました。)

冒頭で、困っていると書きましたが、これを回避する方法はいくつか思いついていますので、
別の方法を教えていただきたいわけではなく、単純になぜこのようなことが起きるのかが知りたいです。
是非よろしくお願いします。

A 回答 (3件)

> Like "A*"



ADO では Like "A%" になると思います。

こういうことではなく、なぜかっていうことになりますか・・・


Access 2003 / 2007 で確認してみました。

Private Sub CheckDAO(sS As String, sSql As String)
  Dim rs As DAO.Recordset

  Set rs = CurrentDb.OpenRecordset(sSql)
  While (Not rs.EOF)
    Debug.Print "DAO" & sS & " : ",
    Debug.Print "顧客id=" & rs("顧客id"),
    Debug.Print "商品id=" & rs("商品id"),
    Debug.Print "式1=" & rs("式1")
    rs.MoveNext
  Wend
  rs.Close
  Set rs = Nothing
End Sub

Private Sub CheckADO(sS As String, sSql As String)
  Dim rs As New ADODB.Recordset

  rs.Source = sSql
  rs.Open , CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
  While (Not rs.EOF)
    Debug.Print "ADO" & sS & " : ",
    Debug.Print "顧客id=" & rs("顧客id"),
    Debug.Print "商品id=" & rs("商品id"),
    Debug.Print "式1=" & rs("式1")
    rs.MoveNext
  Wend
  rs.Close
End Sub

Public Sub test21()
  Const CSQL As String = "SELECT * FROM q_test;"
  Const CSQL2 As String = "SELECT * FROM q_test2;"

  Call CheckDAO("", CSQL)
  Call CheckADO("", CSQL)
  Call CheckDAO("2", CSQL2)
  Call CheckADO("2", CSQL2)
End Sub


クエリ q_test2 は、 A* を A% に変更しただけのもので、
test21 を実行した結果は以下

DAO : 顧客id=1 商品id=A-1 式1=1
DAO : 顧客id=2 商品id=A-2 式1=1
DAO : 顧客id=3 商品id=B-1 式1=0
DAO : 顧客id=4 商品id=A-1 式1=1
ADO : 顧客id=1 商品id=A-1 式1=0
ADO : 顧客id=2 商品id=A-2 式1=0
ADO : 顧客id=3 商品id=B-1 式1=0
ADO : 顧客id=4 商品id=A-1 式1=0
DAO2 : 顧客id=1 商品id=A-1 式1=0
DAO2 : 顧客id=2 商品id=A-2 式1=0
DAO2 : 顧客id=3 商品id=B-1 式1=0
DAO2 : 顧客id=4 商品id=A-1 式1=0
ADO2 : 顧客id=1 商品id=A-1 式1=1
ADO2 : 顧客id=2 商品id=A-2 式1=1
ADO2 : 顧客id=3 商品id=B-1 式1=0
ADO2 : 顧客id=4 商品id=A-1 式1=1

クエリを直接開いた時の表示は、

「q_test」
顧客id 商品id  式1
1    A-1    1
2    A-2    1
3    B-1    0
4    A-1    1

「q_test2」
顧客id 商品id  式1
1    A-1    0
2    A-2    0
3    B-1    0
4    A-1    0


ANSI-92 / ANSI-89 ・・・なんちゃらがあり
http://office.microsoft.com/ja-jp/access-help/HP …
(DAO / ADO の違いについてのお話ではないと思いますが・・・)

ツール→オプションを表示し、
「テーブル/クエリ」のSQLサーバー互換構文(ANSI 92)の
「このデータベース」のチェックを入れ、クエリを直接開くと結果は逆になります。
でも、DAO / ADO での取得(test21 の実行)結果は変わりません。

この辺の動きを説明されているのが以下でしょうか(拡大解釈かも)

ADOとDAOを使用したwhere句内の文字列検索にて、*と%の動きの違い
http://www.nurs.or.jp/~ppoy/access/access/acM012 …

クエリ名で指定しても、その内容の全ての解釈は統一された、
という事になるのでしょうか。(私の解釈ですけど)


うそかも・・・ 自己責任にて解釈してください。
    • good
    • 1

クエリのデザイングリッドのところでSQLビューを表示すると、SQL文がどういうようになっているか分かるのではないですか。


<--ここがミソ
そのSQL文を間違いなく写して
Sub test15()
Dim dbs As DAO.Database
Dim rs As DAO.Recordset

Set dbs = CurrentDb
Set rs = dbs.OpenRecordset("select 氏名,住所 from 社員3")
rs.MoveFirst
Do Until rs.EOF
MsgBox rs!住所
rs.MoveNext
Loop
rs.Close: Set rs = Nothing
dbs.Close: Set dbs = Nothing
End Sub
でselect 氏名,住所 from 社員3の部分を変えて
そのSQL文で実行して何かヒントが得られないですか。
(ちなみに上記は私のテストデータでは動きます。)
ADOでやるならSQL文で開くコードでやってみるとか。
    • good
    • 0

rodoniさん はじめまして。



私も同じようにAccess2003,EXCEL2003で作成し試してみました。
結論か言うと、ADOでもDAOも結果が同じでした。
※下記のプログラムと結果参照

参照設定(ADOのバージョン等)とか環境とか何か違いがあるのでしょうかね?
※DAOは3.6,ADOは6.0で確認

あまりお役に立てず、申し訳ありません。

以下、サンプルと結果です。
【DAO ソース】
Sub DAO_Access()
Dim objDtbs As DAO.Database
Dim objRcrd As DAO.Recordset

Set objDtbs = OpenDatabase(ThisWorkbook.Path & "\" & "test.mdb")
Set objRcrd = objDtbs.OpenRecordset("SELECT * FROM q_test", dbOpenForwardOnly)
With objRcrd
 Do While Not (objRcrd.EOF)
  Debug.Print "顧客id="; objRcrd.Fields("顧客id"),
  Debug.Print "商品id="; objRcrd.Fields("商品id"),
  Debug.Print "式1="; objRcrd.Fields("式1")
  objRcrd.MoveNext
 Loop
End With
objRcrd.Close
objDtbs.Close
Set objRcrd = Nothing
Set objDtbs = Nothing
End Sub
【DAO 結果】
顧客id=1 商品id=A-1 式1= 1
顧客id=2 商品id=A-2 式1= 1
顧客id=3 商品id=B-1 式1= 0
顧客id=4 商品id=A-1 式1= 1

【ADO ソース】
Sub ADO_Access()
 Dim adoCON As New ADODB.Connection
 Dim adoRS As ADODB.Recordset
 adoCON.Open "Driver={Microsoft Access Driver (*.mdb)}; DBQ=" & ThisWorkbook.Path & "\" & "test.mdb"
 Set adoRS = adoCON.Execute("select * from q_test")
 Do While Not (adoRS.EOF)
  Debug.Print "顧客id="; adoRS("顧客id"),
  Debug.Print "商品id="; adoRS("商品id"),
  Debug.Print "式1="; adoRS("式1")
  adoRS.MoveNext
 Loop
 adoRS.Close
 adoCON.Close
 Set adoRS = Nothing
 Set adoCON = Nothing
End Sub
【ADO 結果】
顧客id=1 商品id=A-1 式1= 1
顧客id=2 商品id=A-2 式1= 1
顧客id=3 商品id=B-1 式1= 0
顧客id=4 商品id=A-1 式1= 1
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A