2015年4月5日日曜日

[MSAccess] テーブルで表示のフォーマットを指定する

Microsoft Access で、テーブルのデータシート ビューの表示でフォーマット(書式)を指定する方法です。

テーブルの場合は、デザイン ビューを開いて、出力フォーマットを指定したいカラム(フィールド)のプロパティから、「書式」を変更します。

テーブルのデータに書式を設定する
https://support.office.com/ja-jp/article/テーブルのデータに書式を設定する

クエリも同様にデザイン ビューを開いて、フィールドを選択して「書式」を変更することで変更できます。いずれも Null の表示には影響しません。

2015年4月4日土曜日

[MSAccess] SELECT INTO でデータ型を指定したい

Microsoft Access の SQL では、SELECT INTO ステートメントとは、テーブルを作成して検索結果を挿入します。作成するテーブルにおけるフィールドのデータ型は、クエリの元になるテーブルのフィールドのデータ型とフィールド サイズを継承しますが、SQL 関数などを使用すると適切なデータ型に判定されません。(多くはテキスト型になる)

■ データを直接指定した場合

以下の結果となりました。(Microsoft Access 2007)
SELECT
  0 As Col1,
  0.1 As Col2,
  50000 As Col3,
  '0' As Col4,
  #2015/04/01# As Col5,
  True As Col6,
  Null As Col7,
  IIF(True, 1) As Col8
INTO テーブル1
上記の実行結果
挿入する値データ型の判定結果
0長整数型 (Long)
0.110 進型 (Decimal)
50000長整数型 (Long)
'0'テキスト型 (Text)
#2015/04/01#日付/時刻型 (Date/Time)
True整数型 (Integer)
Nullバイナリ型 (Binary)
IIF関数長整数型 (Long)
今回は、それなりに判定されています。

■ データ型変換関数を使う場合

期待通りのデータ型に判定されていないなら、数値型等のデータ型を指定する場合は、データ型変換関数を使うことで判定を誘導できる。ただしデータ型変換関数では Null はエラーになってしまうため、Not Null 制約がある項目でしか使えない。
データ型変換関数データ型の判定結果
CBool(1)整数型 (Integer)
CByte(1)整数型 (Integer)
CCur(1)通貨型 (Currency)
CDate(1)日付/時刻型 (Date/Time)
CDbl(1)倍精度浮動小数点型 (Double)
CInt(1)整数型 (Integer)
CLng(1)長整数型 (Long)
CSng(1)倍精度浮動小数点型 (Double)
CVar(1)テキスト型 (Text)
CStr(1)テキスト型 (Text)
これも、それなりに判定されています。(完全ではない)

■ データ型変換関数を使う + Null 対策あり

Null 対策が必要であれば、ひと工夫してみると・・・、Null の場合はこの足し算結果が Null になるが、実行時エラーにはならない。
1 + CBool(True)倍精度浮動小数点型 (Double)
1 + CByte(1)倍精度浮動小数点型 (Double)
1 + CDate(1)日付/時刻型 (Date/Time)
1 + CDbl(1)倍精度浮動小数点型 (Double)
1 + CInt(1)倍精度浮動小数点型 (Double)
1 + CLng(1)倍精度浮動小数点型 (Double)
1 + CSng(1)倍精度浮動小数点型 (Double)
ほとんど「倍精度浮動小数点型」に判定されてしまった。

■参考資料

SELECT.INTO ステートメント (Microsoft Access SQL)
https://msdn.microsoft.com/ja-jp/library/office/ff192059.aspx

Access クエリで、CDec() 関数を使用すると、エラー メッセージ:「指定した式に含まれる関数で、引数の数が一致しません。」
http://support.microsoft.com/ja-jp/kb/225931/ja

データ型変換関数 (Visual Basic)
https://msdn.microsoft.com/ja-jp/library/s2dy91zy.aspx

Microsoft Access SQL リファレンス
https://msdn.microsoft.com/ja-jp/library/office/dn123881.aspx

[VBA] テーブルのフィールド名・データ型の一覧を表示

VBA で Microsoft Access テーブルのフィールド名、およびデータ型の一覧を表示するサンプルです。
ShowFields の引数に確認したいテーブル名を指定します。結果はイミディエイト ウィンドウに表示します。
Sub ShowFields(TableName As String)
    Dim Database As DAO.Database
    Dim Field As DAO.Field

    Set Database = CurrentDb
    For Each Field In Database.TableDefs(TableName).Fields
        Debug.Print Field.Name & vbTab & GetTypeName(Field.Type)
    Next
End Sub

Function GetTypeName(Value As DataTypeEnum) As String
    Select Case Value
    Case DataTypeEnum.dbBigInt
        GetTypeName = "多倍長整数型 (Big Integer)"
    Case DataTypeEnum.dbBinary
        GetTypeName = "バイナリ型 (Binary)"
    Case DataTypeEnum.dbBoolean
        GetTypeName = "ブール型 (Boolean)"
    Case DataTypeEnum.dbByte
        GetTypeName = "バイト型 (Byte)"
    Case DataTypeEnum.dbChar
        GetTypeName = "文字型 (Char)"
    Case DataTypeEnum.dbCurrency
        GetTypeName = "通貨型 (Currency)"
    Case DataTypeEnum.dbDate
        GetTypeName = "日付/時刻型 (Date/Time)"
    Case DataTypeEnum.dbDecimal
        GetTypeName = "10 進型 (Decimal)"
    Case DataTypeEnum.dbDouble
        GetTypeName = "倍精度浮動小数点型 (Double)"
    Case DataTypeEnum.dbFloat
        GetTypeName = "浮動小数点型 (Float)"
    Case DataTypeEnum.dbGUID
        GetTypeName = "GUID 型 (GUID)"
    Case DataTypeEnum.dbInteger
        GetTypeName = "整数型 (Integer)"
    Case DataTypeEnum.dbLong
        GetTypeName = "長整数型 (Long)"
    Case DataTypeEnum.dbLongBinary
        GetTypeName = "ロング バイナリ型 (Long Binary)"
    Case DataTypeEnum.dbMemo
        GetTypeName = "メモ型 (Memo)"
    Case DataTypeEnum.dbNumeric
        GetTypeName = "数値型 (Numeric)"
    Case DataTypeEnum.dbSingle
        GetTypeName = "単精度浮動小数点型 (Single)"
    Case DataTypeEnum.dbText
        GetTypeName = "テキスト型 (Text)"
    Case DataTypeEnum.dbTime
        GetTypeName = "時刻型 (Time)"
    Case DataTypeEnum.dbTimeStamp
        GetTypeName = "タイムスタンプ型 (TimeStamp)"
    Case DataTypeEnum.dbVarBinary
        GetTypeName = "可変長バイナリ型 (VarBinary)"
    Case Else
        GetTypeName = "undefined"
    End Select
End Function

■ 参考資料

Field.Type プロパティ (DAO)
https://msdn.microsoft.com/ja-jp/library/office/ff845405.aspx

DataTypeEnum 列挙 (DAO)
https://msdn.microsoft.com/JA-JP/library/office/ff194420.aspx

[Windows] svchost の詳細を確認する

svchost.exe はタスク マネージャで複数確認できるプロセスで、比較的多くのメモリを使用していることが多い。svchost は Windows に登録しているサービスを実行するプロセスなので、svchost のプロセスの子プロセスとして複数のサービスのプロセスを持っている。

svchost がどのサービスを起動しているのか確認するには、複数の方法がある。

タスク マネージャで確認する

svchost.exe で現在実行されているサービスを確認するには
http://windows.microsoft.com/ja-jp/windows/what-is-svchost-exe

コマンドで確認する

tasklist コマンドで確認することができる。
tasklist /fi "imagename eq svchost.exe" /svc

ツールで確認する

Process Explorer ではプロセスツリーをGUIで確認することができる。
https://technet.microsoft.com/ja-jp/sysinternals/bb896653.aspx

2015年4月2日木曜日

[Access] 副問合せを外部結合する際のNull判定タイミング

Microsoft Access SQL における問題です。

副問合せもしくは別のクエリを外部結合した場合に、外部結合側にある Null 判定が動作するタイミングが副問合せの検索段階で終わっておらず、どうやら外部結合後に動作するために想定外の結果が返ることがある。

(例)今月購入して、発送日がNull(未発送)の取引を探す

サンプルデータ

顧客マスタ
顧客番号名前
01顧客01
02顧客02

購入履歴
顧客番号購入日発送日
012015/04/01Null
022014/04/012014/04/03

副問合せを外部結合するSQL

SELECT 顧客マスタ.顧客番号, 今月度.発送状況
FROM 顧客マスタ
LEFT OUTER JOIN (
  SELECT
    顧客番号,
    IIf(発送日 Is Null, '未発送') AS 発送状況
  FROM 購入履歴 
  WHERE #2015/04/01# <= 購入日
) AS 今月度 ON
  顧客マスタ.顧客番号 = 今月度.顧客番号;

予想される結果

顧客番号発送状況
01未発送
02Null

Access SQL での実行結果

顧客番号発送状況
01未発送
02未発送

考察

これは外部結合側でNull判定をする場合に問題となる。

外部結合であると「顧客02」は今月の購入履歴レコードが無いため、副問合せの結果(発送状況)は通常なら Null であると思われる。
しかし、副問合せにある IIf 関数が動作するタイミングがどうやら「副問合せの検索段階」ではなく「外部結合後」であるため、発送日が Null と判定されて「見発送」となってしまう。これは外部結合の結果について、副問合せ内の IIF 関数が判定していると言える。

[Access] SQLでSUMIF関数を使いたい

Excel には SUMIF 関数があるが、Access の SQL関数には同等なものが見当たらない。ただし、SUM と IIF 関数を合わせて同等なものを実現すれば、副問合せを使わずに簡潔に実現できる。

(例)デジタルコンテンツを除いて在庫数を算出する。
デジタルコンテンツの在庫数はゼロとするが、これ以外は「入荷数 - 販売数」を在庫数とする。

SELECT
  商品名,
  SUM(IIF(商品区分='デジタルコンテンツ', 0, 入荷数 - 販売数)) As 在庫数
FROM 商品
GROUP BY 商品名