データベースのField情報の取得

カテゴリー名: [ADOによるデータベースの中身の把握

2016/11/23

 データベース操作のうち、Fieldに関する情報の把握を取り上げます。

 素材となる TestDB.mdb の作成方法については「データベースのTable情報の取得」を参照してください。

関連の Program Page

    


《このページの目次》


    

1. フィールドの基本的な情報

 Accessデータベースの中身を把握するには、Table情報に加えて Field情報も見る必要があります。

 「データベースのTable情報の取得」のところでは Tableオブジェクトの Name, Type を見ましたが、他に Columns というプロパティがあります。これを見ると Field情報を知ることができます。

 Field情報にはいろいろなものがありますが、基本となるのは次の三つです。

  1. Name: フィールドの名前(文字列)。TestDB.mdbの場合でいうと、ID、性別、身長といった名前のことです。
  2. Type: フィールドのデータ型(数値)。
     SQL表記でいうと varchar, int, float, date などに当たります。
  3. DefinedSize: フィールドの最大桁数。varchar(10) だと 10 がそれです。

 これらを知るには下のプロパティを見ます。

TableObject.Columns(0).Name
TableObject.Columns("ID").Type
TableObject.Columns("職業").DefinedSize

 フィールド(Column)の指定は、番号または名前のどちらでも行えます。

 Columns(0) とか Columns("職業") などと書くことができます。

 番号は 0 から始まります。

    

(1) フィールドのデータ型

 データ型を示す Type は、文字列でなく数値です。おおよそ次のようなものがあります。

数値 定数名 意味 SQL表記
2 adSmallInt 符号付き整数・約+-3万2千以内 smallint integer2 short
3 adInteger 符号付き整数・約+-21億以内 int integer integer4 long
4 adSingle 単精度浮動小数点 real float4
5 adDouble 倍精度浮動小数点 float double float8
6 adCurrency 通貨 money
7 adDate 日付型 date time datetime smalldatetime
8 adBSTR 文字列値 □□
9 adIDispatch COMオブジェクトのIDispatchへのポインタ □□
10 adError 32ビットエラーコード □□
11 adBoolean Yes|No型 bit yesno logical
12 adVariant オートメーションバリアント型 □□
13 adIUnknown COMオブジェクトのIUnknownインターフェイスへのポインタ □□
14 adDecimal 固定精度・スケールの正確な数値 □□
16 adTinyInt 符号付き整数・-128→+127 □□
17 adUnsignedTinyInt 符号なし整数・0→255 tinyint
18 adUnsignedSmallInt 符号なし整数・約6万5千以下 □□
19 adUnsignedInt 符号なし整数・約42億以下 □□
20 adBigInt 符号付き整数・特大 □□
21 adUnsignedBigInt 符号なし整数・特大 □□
64 adFileTime 時間・1601年1月1日からの時間 □□
72 adGUID 固有のグローバル識別子GUID guid
128 adBinary バイナリ □□
129 adChar 文字列値 □□
130 adWChar 固定長文字列・最長255桁 char nchar
131 adNumeric 固定精度・スケールの正確な数値 decimal dec numeric
132 adUserDefined ユーザー定義変数 □□
133 adDBDate 日付・yyyymmdd □□
134 adDBTime 時刻・hhmmss □□
135 adDBTimeStamp 日付時刻・yyyymmddhhmmss+α □□
136 adChapter 子行セットの行を識別する4バイトチャプタ値 □□
138 adPropVariant オートメーションPROPVARIANT □□
139 adVarNumeric 数値 □□
200 adVarChar 文字列値 □□
201 adLongVarChar 長文字列 □□
202 adVarWChar 可変長文字列・最長255桁 varchar nvarchar
203 adLongVarWChar 長文字列 longtext memo note
204 adVarBinary バイナリ型・最長510桁 binary varbinary
205 adLongVarBinary 長バイナリ・OLEオブジェクト型 longbinary image general

    

 SQL表記が「□□」になっているのは、該当する表記が分からなかったものです。

 これらは、該当の表記がないような気がしますが、筆者が分からなかっただけかもしれません。

 Northwind.mdb で使われているデータ型は、すべて上の表のSQL表記で示すことができます。

目次に戻る


    

(2) フィールドの最大桁数

 フィールドの最大桁数は、SQL表記でいうと varchar(10) の文字列型の場合の長さ 10 のことです。varcharの場合は 255以下で指定します。

 この数は、文字数を表します。半角も全角も同じ1文字としてカウントします。バイト数(半角文字数)ではありません。

 短いバイナリデータを binary(128) と指定したときは、最大桁数が 128 となります。510桁(つまり 510バイト)以内で指定します。

 最大桁数を超えるデータを書き込もうとしても、エラーが発生します。

 あと、真偽(True, False)を示すデータ型のサイズは、なぜか 2 です。
といっても、SQL表記ではこの桁数を書いたりはしません。2 という値は気にする必要がないとおもいます。

 そのほか、多くのデータ型は、サイズが 0 です。

 長い文字列の longtext、長いバイナリの longbinary
日付型の date、数値を示す int, float, money など、いずれも最大桁数が 0 です。

    

 定数名 adNumeric(固定精度・スケールの正確な数値)のデータ型の場合は、次のプロパティが値を持ちます。なお、最大桁数(DefinedSize)は 0 です。

  1. Precision: 数値全体の最大桁数
  2. NumericScale: 小数部の最大桁数

 SQL表記で decimal(20, 4) と書くと、Precision=20, NumericScale=4 となります。

 Precision の 20 は、小数部を含む数値全体の最大桁数なので、
整数部分の桁数は 20 - 4 = 16 程度となります。

目次に戻る


    

(3) デフォルト値と空欄禁止

 フィールドに関する情報は様々ありますが、「デフォルト値」と「空欄禁止」について見てもみます。

 「デフォルト値」は、入力が省略されたときにセットされる値です。

 SQL記述で 職業 varchar(20) default 無職 とフィールドを定義すると、
データベース操作の段階で「職業」の欄に何も書かない場合、
「無職」が自動的に書き込まれます。

 「デフォルト値」を見るには次のプロパティを参照します。

TableObject.Columns("職業").Properties("Default").Value

    

 「空欄禁止」は、必ず何かを書き込まなければならないとの指定です。

 SQL命令では not null を書いて指定します。たとえば
職業 varchar(20) not null と定義すると、「職業」というフィールドが空欄禁止になります。

 データベース操作のときに「職業」の入力を省略するとエラーになります。

 フィールドが「空欄禁止」になっているかどうかを知るには、次のプロパティを見ます。

TableObject.Columns("職業").Properties("NULLable").Value

 上のプロパティが False であれば「空欄禁止」です。
True になっていれば「空欄許可」です。

目次に戻る


    

(4) オートナンバー

 データベース操作の段階で入力を省略すると、自動的に番号が入力されるフィールドがあります。オートナンバーのフィールドです。

 ID(識別番号)のフィールドがオートナンバーになっている場合があります。

 AccessデータベースのSQL表記のケースでいうと、ID int と書くところを
ID counter(10,5) のように書きます。すると、「ID」というフィールドがオートナンバー形式になります。

 この場合、10, 15, 20, 25, 30, …… と進んでいきます。

 counter(10,5) の 10 が初期値、5 が増分値です。

    

 オートナンバーに関するプロパティは継ぎの三つです。

TableObject.Columns("ID").Properties("Autoincrement").Value → True|False
TableObject.Columns("ID").Properties("Seed").Value → 初期値
TableObject.Columns("ID").Properties("Increment").Value → 増分値

 Properties("Autoincrement").Value が True であれば該当のフィールドがオートナンバー型です。

 Properties("Seed").Value の初期値は、データベースにレコードを追加する度に増えていきます。テーブルを定義したときは 1 だったとしても、レコードを追加すると 2, 3, 4, …… と増えていきます。

 増分値は、定義の際に省略すると 1 になります。counter(10) だと、10, 11, 12, 13, …… と進みます。

目次に戻る


    

2. VBAマクロ

 データベースのフィールド情報を出力する VBAマクロを掲げます。Excel用のマクロです。ADO, ADOX への参照設定が行われているとの前提で書かれています。

 Macro1 を実行するとデータベース名を入力する場面になります。適当に入力してエンターキーを押します。

 すると、ワークシートにテーブルめいとそのフィールド情報が書き出されます。

 書き出されるフィールド情報は下の3種類です。

  1. フィールドの名前、種類(TABLE|VIEW)
  2. データ型を示す定数名
  3. フィールド情報をSQL表記にしたもの

 SQL表記の中には primary key あるいは unique が出てくる場合があります。

 これらは、インデックス情報と関連します。それについては、このページの最後の方で簡単に触れます。

    

△ macro02.txt

 1' Accessデータベースのフィールド情報の取得
 2Sub Macro1()
 3    Dim DbName As String, DbPath As String, ConnStr As String
 4    Dim FSO As Object, TypeCst As Object, TypeSql As Object
 5    Dim CN As ADODB.Connection, CAT As ADOX.Catalog
 6    Dim Tbl As Variant, FldName As Variant, Col As Object
 7    Dim TypeStr As String, IdxHash As Object, Ary As Object, i As Integer
 8
 9    Set FSO = CreateObject("Scripting.FileSystemObject")
10    DbName = InputBox("Accessファイルの名前: ", _
11        "Accessフィールド情報取得", "TestDB.mdb")
12    If DbName = "" Then Exit Sub
13    CreateObject("WScript.Shell").CurrentDirectory = ThisWorkbook.Path
14    DbPath = FSO.GetAbsolutePathName(DbName)
15    If FSO.FileExists(DbPath) = False Then
16        MsgBox "ファイルがみつかりません: " & DbPath
17        Exit Sub
18    End If
19
20    ConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DbPath & ";"
21    Set CN = New ADODB.Connection
22    CN.Open ConnStr
23    Set CAT = New ADOX.Catalog
24    CAT.ActiveConnection = CN
25    Set TypeCst = TypeCstHash()  ' データ型:番号と定数名の関連付け
26    Set TypeSql = TypeSqlHash()  ' データ型:番号とSQL表記の関連付け
27
28    Set Ary = CreateObject("System.Collections.ArrayList")
29    For Each Tbl In CAT.Tables  ' テーブルを一つずつたどる
30        If (Tbl.Type = "TABLE") Or (Tbl.Type = "VIEW") Then
31            FldName = GetFieldName(CN, Tbl.Name)  ' フィールド名一覧を取得
32            Ary.Add Array(Tbl.Name, Tbl.Type)
33            Set IdxHash = IndexHash(Tbl)
34            For i = 0 To UBound(FldName)  ' フィールドを一つずつ
35                Set Col = Tbl.Columns(FldName(i))
36                TypeStr = FieldSqlStr(Col, TypeSql)
37                If IdxHash.Exists(Col.Name) Then
38                    TypeStr = TypeStr & " " & IdxHash(Col.Name)
39                End If
40                Ary.Add Array("", Col.Name, TypeCst(Col.Type), TypeStr)
41            Next
42            Ary.Add Array("")
43        End If
44    Next
45    CN.Close
46
47    ActiveSheet.UsedRange.Clear
48    For i = 0 To (Ary.Count-1)
49        Range(Cells(i+1, 1), Cells(i+1, UBound(Ary(i))+1)).Value = Ary(i)
50    Next
51    For i = 1 To ActiveSheet.UsedRange.Columns.Count
52        ActiveSheet.UsedRange.Columns(i).AutoFit
53    Next
54End Sub
55
56    (以下、関数部分は省略)

    

 配列操作にかかわる System.Collections.ArrayList については、下のサイトが分かりやすく参考になります。

実験記録 No.02 : VBSで動的配列(ArrayList)を使う

    

(1) フィールドの順番

 フィールド情報を取り出すのに TableObject.Columns を使いますが、このプロパティは、フィールドの順番を保持していません。

 「ID、性別、身長、体重」の順番で定義したのに、TableObject.Columns を一つずつ取り出すと、「ID、体重、性別、身長」の順番になる、といった具合です。

 これだと不都合なので、データベースのレコードのうち、第1レコードだけをチェックし、フィールドの名前を取り出します。こちらは、定義したとおりの順番です。

 この処理をやっているのが関数 GetFieldName(CN, TblName) です。

 この関数は、フィールド名を配列に入れて返します。

 該当部分を掲げます。

    

 1Function GetFieldName(CN, ByVal TblName)  ' フィールド名の取得
 2    Dim RS As ADODB.Recordset, FldName() As Variant
 3    Dim FldCount As Integer, i As Integer
 4    TblName = "[" & TblName & "]"
 5    Set RS = New ADODB.Recordset
 6    RS.Open TblName,CN,0,1,2
 7    FldCount = RS.Fields.Count
 8    ReDim FldName(FldCount-1)
 9    For i = 0 To (FldCount-1)
10        FldName(i) = RS.Fields(i).Name
11    Next
12    RS.Close
13    Set RS = Nothing
14    GetFieldName = FldName
15End Function

目次に戻る


    

(2) フィールド情報をSQL表記に変換

 関数 FieldSqlStr(Col, TypeSql) は、フィールド情報をSQL表記にした文字列を返します。

 第2パラメータの TypeSql は、Dictionaryオブジェクトといわれるものです。

 プログラムの別の箇所で、整数値を文字列に変換するハッシュテーブルとして定義しています。

 TypeSql(5)"float" という文字列となり、
 TypeSql(200) なら "varchar" という文字列です。

 これだけだと、最大桁数、デフォルト値、空欄禁止、オートナンバー型かどうかといった情報がないので、関数 FieldSqlStr の中でそうした情報を付け加えています。

 VBAマクロの関連する部分を掲げます。

    

 1Function FieldSqlStr(Col, TypeSql)  ' フィールド情報をSQL表記に
 2    Dim TypeStr As String, Val As Variant
 3    If Col.Properties("Autoincrement").Value = True Then
 4        TypeStr = "counter(" & Col.Properties("Seed").Value & _
 5            "," & Col.Properties("Increment").Value & ")"
 6    Else
 7        TypeStr = TypeSql(Col.Type)
 8    End If
 9    If (Col.DefinedSize > 0) And (Col.Type <> adBoolean) Then _
10        TypeStr = TypeStr & "(" & Col.DefinedSize & ")"
11    If Col.Type = adNumeric Then _
12        TypeStr = TypeStr & "(" & Col.Precision & ", " & _
13            Col.NumericScale & ")"
14    Val = Col.Properties("Default").Value
15    If Val <> "" Then
16        If InStr(Val, " ") Then Val = "[" & Val & "]"
17        TypeStr = TypeStr & " DEFAULT " & val
18    End If
19    Val = Col.Properties("NULLable").Value
20    If Val = False Then
21        TypeStr = TypeStr & " NOT NULL"
22    End If
23    FieldSqlStr = TypeStr
24End Function
25
26Function TypeSqlHash()
27    Dim TypeSql As Object
28    Set TypeSql = CreateObject("Scripting.Dictionary")
29    TypeSql.Add 2, "SmallInt"
30    (中略)
31    Set TypeSqlHash = TypeSql
32End Function

目次に戻る


    

3. OLEを利用したVBScript

 Accessデータベースのフィールド情報を FieldInfo.txt というテキストファイルに書き出すVBScriptを掲げます。

 処理の手順は先の macro02.txt と同じです。

 ADO用の定数を定義したファイル constants_ad.vbs を読み込む形になっています。

 constants_ad.vbs の中で、次の二つの関数も定義しています。

  1. TypeCstHash: データベースのデータ型についてその番号と定数名の関連付け
  2. TypeSqlHash: データベースのデータ型についてその番号とSQL表記の関連付け

 上のどちらも Dictionaryオブジェクト(ハッシュ)を返します。

    

△ vovTBL02.vbs

 メイン部分のみ掲げます。関数の部分は、VBAマクロとほぼ共通です。

 1' Accessデータベースのフィールド情報を取得
 2Option Explicit
 3Dim FSO, Fobj, DbName, DbPath, TypeCst, TypeSql
 4Dim ConnStr, CN, CAT, Tbl, FldName, Col, Ary, TypeStr, IdxHash, i
 5Include "constants_ad.vbs"
 6
 7Set FSO = CreateObject("Scripting.FileSystemObject")
 8DbName = InputBox("Accessファイルの名前: ", _
 9    "Accessフィールド情報取得", "TestDB.mdb")
10If DbName = "" Then WScript.Quit
11DbPath = FSO.GetAbsolutePathName(DbName)
12If FSO.FileExists(DbPath) = False Then
13    MsgBox "ファイルがみつかりません: " & DbPath
14    WScript.Quit
15End If
16
17ConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DbPath & ";"
18Set CN = CreateObject("ADODB.Connection")
19CN.Open ConnStr
20Set CAT = CreateObject("ADOX.Catalog")
21CAT.ActiveConnection = CN
22Set TypeCst = TypeCstHash()  ' データ型:番号と定数名の関連付け
23Set TypeSql = TypeSqlHash()  ' データ型:番号とSQL表記の関連付け
24
25Set Ary = CreateObject("System.Collections.ArrayList")
26For Each Tbl In CAT.Tables  ' テーブルを一つずつたどる
27    If (Tbl.Type = "TABLE") Or (Tbl.Type = "VIEW") Then
28        FldName = GetFieldName(CN, Tbl.Name)  ' フィールド名一覧を取得
29        Ary.Add Array("*" & Tbl.Name, Tbl.Type)
30        Set IdxHash = IndexHash(Tbl)
31        For i = 0 To UBound(FldName)  ' フィールドを一つずつ
32            Set Col = Tbl.Columns(FldName(i))
33            TypeStr = FieldSqlStr(Col, TypeSql)
34            If IdxHash.Exists(Col.Name) Then
35                TypeStr = TypeStr & " " & IdxHash(Col.Name)
36            End If
37            Ary.Add Array("", Col.Name, TypeCst(Col.Type), TypeStr)
38        Next
39        Ary.Add Array("")
40    End If
41Next
42CN.Close
43Set Fobj = FSO.OpenTextFile("FieldInfo.txt", 2, True)
44For i = 0 To (Ary.Count-1)
45    Fobj.WriteLine Join(Ary(i), vbTab)
46Next
47Fobj.Close
48
49    (以下、後略)

目次に戻る


    

4. Jscript

 先の vovTBL02.vbs と同じ処理を行う JScript を掲げます。

 constants_ad.js を読み込む形になっています。

 やはり、メイン部分だけを掲げます。関数については Program Page を参照して下さい。

△ vovTBL02.js

 1// Accessデータベースのフィールド情報の取得
 2var fso, Fobj, dbName, dbPath, typeCst, typeSql;
 3var connStr, cn, cat, tbl, fldName, idxHash, col, Ary, i, j;
 4eval(ReadFile("constants_ad.js"));
 5
 6fso = WScript.CreateObject("Scripting.FileSystemObject");
 7dbName = InputBox("Accessファイルの名前: ",
 8    "Accessフィールド情報取得", "TestDB.mdb");
 9if (dbName == "")  WScript.Quit();
10dbPath = fso.GetAbsolutePathName(dbName);
11if (fso.FileExists(dbPath) == false) {
12    var shellObj = WScript.CreateObject("WScript.Shell");
13    WScript.Echo("ファイルがみつかりません: " + dbPath);
14    while (shellObj.AppActivate("Windows Script Host") != true) {
15        WScript.Sleep(100);
16    }
17    WScript.Quit();
18}
19
20connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + dbPath + ";";
21cn = WScript.CreateObject("ADODB.Connection");
22cn.Open(connStr);
23cat = WScript.CreateObject("ADOX.Catalog");
24cat.ActiveConnection = cn;
25typeCst = TypeCstHash();  // データ型:番号と定数名の関連付け
26typeSql = TypeSqlHash();  // データ型:番号とSQL表記の関連付け
27
28Ary = [];
29for (i=0; i<cat.Tables.Count; i++) {  // テーブルを一つずつたどる
30    tbl = cat.Tables(i);
31    if (tbl.Type == "TABLE" || tbl.Type == "VIEW") {
32        Ary.push(["*" + tbl.Name, tbl.Type]);
33        fldName = GetFieldName(cn, tbl.Name);  // フィールド名一覧を取得
34        idxHash = IndexHash(tbl);
35        for (j=0; j<fldName.length; j++) {  // フィールドを一つずつ
36            col = tbl.Columns(fldName[j]);
37            typeStr = FieldSqlStr(col, typeSql);
38            if (idxHash[col.Name] != null)
39                typeStr = typeStr + " " + idxHash[col.Name];
40            Ary.push(["", col.Name, typeCst[col.Type], typeStr]);
41        }
42        Ary.push([""]);
43    }
44}
45cn.Close();
46Fobj = fso.OpenTextFile("FieldInfo.txt", 2, true);
47for (i = 0; i < Ary.length; i++) {
48    Fobj.WriteLine(Ary[i].join("\t"));
49}
50Fobj.Close();
51
52    (以下、省略)

目次に戻る


    

5. インデックス

 インデックス(索引)は、検索を素早く行うために設けられるものです。

 何万件、何十万件と登録されているデータベースに対して、いつも先頭から最後に向かって素直に検索していたのでは、最後の方のデータを取り出すのに時間がかかってしようがありません。

 そこで索引を設けて効率的に検索できるようにします。

 といっても、インデックスは、データベースシステムが自動的に作成・管理してくれるので、ユーザー側が意識して作成する必要はありません。

 ここではインデックスについて説明するというよりも、フィールド情報との関連で言及するだけなので、主キー(primary key)、重複禁止(unique)に関して簡単に述べます。

    

(1) 主キーと重複禁止

 主キーは、一つのレコードを取り出すのに手がかりとするメインのフィールドのことです。

 各々のレコードにID番号(識別番号)を割り当てて主キーにするというのは、よくある手です。

 テーブルを定義するときに ID int primary key とすれば「ID」が主キーになります。

 数あるレコードの中から特定の一つのレコードを取り出す手がかりですから、他のレコードの同じ値がセットされていると不都合です。

 となると、レコードを登録する際に「重複したものがないかどうか」をチェックしなければなりません。つまり検索が必要になります。

 そこで、データベースシステムは、インデックスを設けて、主キーに指定されたフィールドをそのインデックスに登録します。それにより暗黙のうちに行う検索を効率化します。

    

 主キーにするわけではなくても、同じフィールドに同じ値のものがあると不都合だという場合があります。

 会員番号、発注コード、契約識別番号等々、入力の際に謝って他と同じ値を入れてしまうと、後でトラブルになります。

 そうしたフィールドは、重複禁止の unique にします。

 そうしておけば、重複したものがあるとエラーが発生して登録できません。トラブルを未然に防ぐことになります。

 SQL表記では定義時に 発注コード int unique のように記述します。

目次に戻る


    

(2) インデックス情報を見る方法

 Accessデータベースのインデックス情報は、TableObject.Indexes で参照できます。

 一つのテーブルに複数のインデックスがある場合があるので Indexes です。

 TableObject.Indexes(0) とか TableObject.Indexes(1) として一つのインデックスオブジェクトを参照することができます。

 TableObject.Indexes(0).PrimaryKey が True であれば、第1のインデックスが主キーに関するものであるということになります。

 TableObject.Indexes(1).Unique が True であれば、第2のインデックスが重複禁止に関するものだということです。

 でも、このインデックスがどのフィールドに関するものなのかがまだ分かりません。

    

 第1のインデックスオブジェクトがどのフィールドに関連しているかを見るには
TableObject.Indexes(0).Columns を参照します。

 ここで出てくる Columns も複数形であることから推測されるように、一つのフィールドだけに関連している訳ではありません。一つだけかもしれないけど、複数の可能性もあります。

 面倒ではありますが、Columns を一つずつ見ていく必要があります。

 TableObject.Indexes(0).Columns(0).Name"ID" という文字列が代入されていれば、「ID」というフィールドが主キーだと分かります。

 なんともややこしいですが、こんなふうにして確認するしかないようです。

    

 ところで、重複禁止の方はともかく、二つ以上のフィールドが主キーになっているというケースがあるのか、とおもわれるかもしれません。

 実は、あります。Northwind.mdb にも一つのテーブルにおいて二つの主キーが指定されているものがあります。

 数あるレコードから一つのレコードを取り出す手がかり(フィールド)が、一つだけでなく二つあるわけです。珍しいとはおもいますが。

 ともあれ、あるフィールドが主キーかどうか、重複禁止かどうかを見るには、
Indexes の下にぶら下がっている Columns を一つずつチェックする必要があります。

    

 こうした構造になっているインデックス情報を、容易に参照できるハッシュの形にまとめるのが関数 IndexHash(Tbl) です。

 VBAの記述でいうと、Set IdxHash = IndexHash(Tbl) とすると、
IdxHash("ID")"primary key" という文字列を保持する、といった具合になります。

 あるいは、IdxHash("発注コード")"unique" を保持するといった具合です。

 以下、関数 IndexHash を掲げます。

    

△ 関数IndexHash

 1Function IndexHash(Tbl)  ' インデックス情報の取得
 2    Dim IdxHash As Object, Idx As Variant, Str As String, Col As Variant
 3    Set IdxHash = CreateObject("Scripting.Dictionary")
 4    For Each Idx In Tbl.Indexes
 5        Str = ""
 6        If Idx.PrimaryKey Then Str = "primary key"
 7        If (Str = "") And Idx.Unique Then Str = "unique"
 8        If Str <> "" Then
 9            For Each Col In Idx.Columns
10                If IdxHash.Exists(Col.Name) = False Then _
11                    IdxHash.Add Col.Name, Str
12            Next
13        End If
14    Next
15    Set IndexHash = IdxHash
16End Function

    

〜 以上 〜