2009-03-30 2 views
22

.mdbデータベースのスキーマを抽出しようとしています。そのため、他の場所でデータベースを再作成できます。Access(.mdb)データベースのスキーマを抽出する方法は?

どうすればこのようなことができますか?

+0

どのような言語ですか?それは問題ですか? –

+0

私は本当にその質問を理解していません。抽出されたテキストは、必要に応じてデータベースを再作成できるように、Access SQLにある必要があります。 – AngryHacker

+0

PythonからADOXを使用する私の答えのように、Access SQLを使用するために_not_を選択すると、言語は関連しています。 AccessデータベースからDDLを構築することは、PITAです(Remouの答えの冗長性によって示されます)。 – mavnn

答えて

18

VBAで少しでも可能です。たとえば、ローカル・テーブルを持つデータベースのスクリプトの作成を開始します。

Dim db As Database 
Dim tdf As TableDef 
Dim fld As DAO.Field 
Dim ndx As DAO.Index 
Dim strSQL As String 
Dim strFlds As String 
Dim strCn As String 

Dim fs, f 

    Set db = CurrentDb 

    Set fs = CreateObject("Scripting.FileSystemObject") 
    Set f = fs.CreateTextFile("C:\Docs\Schema.txt") 

    For Each tdf In db.TableDefs 
     If Left(tdf.Name, 4) <> "Msys" Then 
      strSQL = "strSQL=""CREATE TABLE [" & tdf.Name & "] (" 

      strFlds = "" 

      For Each fld In tdf.Fields 

       strFlds = strFlds & ",[" & fld.Name & "] " 

       Select Case fld.Type 

        Case dbText 
         'No look-up fields 
         strFlds = strFlds & "Text (" & fld.Size & ")" 

        Case dbLong 
         If (fld.Attributes And dbAutoIncrField) = 0& Then 
          strFlds = strFlds & "Long" 
         Else 
          strFlds = strFlds & "Counter" 
         End If 

        Case dbBoolean 
         strFlds = strFlds & "YesNo" 

        Case dbByte 
         strFlds = strFlds & "Byte" 

        Case dbInteger 
         strFlds = strFlds & "Integer" 

        Case dbCurrency 
         strFlds = strFlds & "Currency" 

        Case dbSingle 
         strFlds = strFlds & "Single" 

        Case dbDouble 
         strFlds = strFlds & "Double" 

        Case dbDate 
         strFlds = strFlds & "DateTime" 

        Case dbBinary 
         strFlds = strFlds & "Binary" 

        Case dbLongBinary 
         strFlds = strFlds & "OLE Object" 

        Case dbMemo 
         If (fld.Attributes And dbHyperlinkField) = 0& Then 
          strFlds = strFlds & "Memo" 
         Else 
          strFlds = strFlds & "Hyperlink" 
         End If 

        Case dbGUID 
         strFlds = strFlds & "GUID" 

       End Select 

      Next 

      strSQL = strSQL & Mid(strFlds, 2) & ")""" & vbCrLf & "Currentdb.Execute strSQL" 

      f.WriteLine vbCrLf & strSQL 

      'Indexes 
      For Each ndx In tdf.Indexes 

       If ndx.Unique Then 
        strSQL = "strSQL=""CREATE UNIQUE INDEX " 
       Else 
        strSQL = "strSQL=""CREATE INDEX " 
       End If 

       strSQL = strSQL & "[" & ndx.Name & "] ON [" & tdf.Name & "] (" 

       strFlds = "" 

       For Each fld In tdf.Fields 
        strFlds = ",[" & fld.Name & "]" 
       Next 

       strSQL = strSQL & Mid(strFlds, 2) & ") " 

       strCn = "" 

       If ndx.Primary Then 
        strCn = " PRIMARY" 
       End If 

       If ndx.Required Then 
        strCn = strCn & " DISALLOW NULL" 
       End If 

       If ndx.IgnoreNulls Then 
        strCn = strCn & " IGNORE NULL" 
       End If 

       If Trim(strCn) <> vbNullString Then 
        strSQL = strSQL & " WITH" & strCn & " " 
       End If 

       f.WriteLine vbCrLf & strSQL & """" & vbCrLf & "Currentdb.Execute strSQL" 
      Next 
     End If 
    Next 

    f.Close 
+2

これは本当に良いです。デフォルト値、外部キーなどをどうやって取得しますか? – AngryHacker

+0

デフォルト値を追加するには、ADOを使用する必要があります。外部キーなどがCONSTRAINT ReferForeignField FOREIGN KEY(、...、)を追加することができ、私は私が例に追加する何ができるかが表示されます

、...、) を参照します。 – Fionnuala

+0

DAOを使用している場合は、リレーションシップコレクションを使用して外部キー制約を適用する必要がありますか? –

1

AccessでDDLスクリプト/クエリを実行するのは難しいです。それはできますが、データベースのコピーを作成するだけで済みます。すべてのデータを削除して圧縮してください。次に、このコピーを使用してデータベースを他の場所に再作成します。

+0

私はこれが答えかもしれないと心配しました。だから、ビルドの統合は問題になりません。 – AngryHacker

+2

それはあなたの質問ではありませんでした。あなたはビルドの統合について尋ねなかったので、スキーマの抽出について尋ねました。アプリケーションの残りの部分とまったく同じように、コードを書くことでスキーマ構築プロセスを確実にスクリプト化することができます。 – dkretz

1

docmdを確認してください。 TransferDatabaseコマンドおそらく、データ構造を複製する必要があるビルド統合のための最良の方法です。

4

あなたが(それはソート、フィルタリングすることができますので、コレクション、などよりも議論の余地優れている)レコードセットとしてスキーマ情報を取得するためにACE /ジェットOLE DBプロバイダーとADOのConnectionオブジェクトのOpenSchemaメソッドを使用することができます。

基本的な方法論は、その後、ORDINAL_POSITIONのためadSchemaColumnsをフェッチするために、各TABLE_NAMEを使用し、ベーステーブル(ないビュー)を取得するためにadSchemaTablesを使用することです!DATA_TYPE、!IS_NULLABLE、!COLUMN_HASDEFAULT、!COLUMN_DEFAULT、!CHARACTER_MAXIMUM_LENGTH、!NUMERIC_PRECISION ,! NUMERIC_SCALE。

adSchemaPrimaryKeysは簡単です。 adSchemaIndexesはUNIQUE制約を見つける場所で、一意のインデックスと区別できないかどうか、adSchemaForeignKeys行セットにプラグインするFOREIGN KEYの名前などがわかりません。 (擬似コード):

rsFK.Filter = "FK_NAME = '" & !INDEX_NAME & "'") 

- ジェット3.51は無名のPK(!!)

検証ルールの名称とCHECK制約に基づいて、FKがで見つけることができる可能落とし穴を監視OpenSchemaの呼び出しでテーブル名を使用してadSchemaTableConstraints行セットを作成し、adSchemaCheckConstraints行セットの呼び出しでCONSTRAINT_TYPE = 'CHECK'をフィルタリングします(gotchaは 'ValidationRule' + Chr $(0)という制約です。名前からヌル文字をエスケープするのが最善です)。 ACE/Jet検証ルールは、行レベルまたはテーブルレベルのいずれでもかまいません(CHECK制約は常にテーブルレベル)ので、フィルタでテーブル名を使用する必要があります。adSchemaTableConstraintsは[]。[]。ValidationRule adSchemaCheckConstraintsの[] .ValidationRuleになります。もう1つの問題(バグが疑われる)は、フィールドの幅が255文字であるため、255文字を超える検証規則/ CHECK制約の定義にはNULL値があります。

adSchemaViewsは、非パラメタライズドSELECT SQL DMLに基づくAccess Queryオブジェクト用ですが、 adSchemaColumnsのVIEW名を使用して列の詳細を取得できます。

プロシージャは、adSchemaProceduresにあります。これは、パラメータ化されたSELECT DMLを含むAccess Queryオブジェクトの他のすべての機能です。後者の場合は、PROCEDURE_DEFINITIONのCREATE PROCEDURE PROCEDURE_NAMEを使用してPARAMETERS構文を置き換えることをお勧めします。 adSchemaProcedureParametersを見ていないと、何も見つかりません。パラメータはADOXコマンドを返すためにADOX Catalogオブジェクトを使って列挙できます。 (擬似コード):

Set Command = Catalog.Procedures(PROCEDURE_NAME).Command 

次いで、IS_NULLABLEため.NAME、DATA_TYPEため.TYPE、(.AttributesそしてadParamNullable)ためComm.Parametersコレクションを列挙する。COLUMN_HASDEFAULTおよびCOLUMN_DEFAULT、.Size、.Precision、.NumericScaleの値。

ユニコード圧縮などのACE/Jet固有のプロパティでは、別の種類のオブジェクトを使用する必要があります。例えば、Access-speakの長整数オートナンバーは、ADO Catalogオブジェクトを使用して見つけることができます。 (擬似コード):

bIsAutoincrement = Catalog.Tables(TABLE_NAME).Columns(COLUMN_NAME).Properties("Autoincrement").Value 

幸運:)

6

あなたは純粋なアクセスSQL以外のものを使用して満足している場合、あなたはADOXオブジェクトのコレクションを持続し、テーブル構造を再作成するために、これらを使用することができます。

例(それは私がに取り組んでいたプロジェクトのために必要されなかったとして、Pythonで、現在の関係とインデックスを再作成しません):

import os 
import sys 
import datetime 
import comtypes.client as client 

class Db: 
    def __init__(self, original_con_string = None, file_path = None, 
       new_con_string = None, localise_links = False): 
     self.original_con_string = original_con_string 
     self.file_path = file_path 
     self.new_con_string = new_con_string 
     self.localise_links = localise_links 

    def output_table_structures(self, verbosity = 0): 
     if os.path.exists(self.file_path): 
      if not os.path.isdir(self.file_path): 
       raise Exception("file_path must be a directory!") 
     else: 
      os.mkdir(self.file_path) 
     cat = client.CreateObject("ADOX.Catalog") 
     cat.ActiveConnection = self.original_con_string 
     linked_tables =() 
     for table in cat.Tables: 
      if table.Type == u"TABLE": 
       f = open(self.file_path + os.path.sep + 
         "Tablestruct_" + table.Name + ".txt", "w") 
       conn = client.CreateObject("ADODB.Connection") 
       conn.ConnectionString = self.original_con_string 
       rs = client.CreateObject("ADODB.Recordset") 
       conn.Open() 
       rs.Open("SELECT TOP 1 * FROM [%s];" % table.Name, conn) 
       for field in rs.Fields: 
        col = table.Columns[field.Name] 
        col_details = (col.Name, col.Type, col.DefinedSize, 
            col.Attributes) 
        property_dict = {} 
        property_dict["Autoincrement"] = (
         col.Properties["Autoincrement"].Value) 
        col_details += property_dict, 
        f.write(repr(col_details) + "\n") 
       rs.Close() 
       conn.Close() 
       f.close() 
      if table.Type == u"LINK": 
       table_details = table.Name, 
       table_details += table.Properties(
        "Jet OLEDB:Link DataSource").Value, 
       table_details += table.Properties(
        "Jet OLEDB:Link Provider String").Value, 
       table_details += table.Properties(
        "Jet OLEDB:Remote Table Name").Value, 
       linked_tables += table_details, 
     if linked_tables !=(): 
      f = open(self.file_path + os.path.sep + 
        "linked_list.txt", "w") 
      for t in linked_tables: 
       f.write(repr(t) + "\n") 
     cat.ActiveConnection.Close() 

同様の逆関数は2番目の接続を使用してデータベースを再構築します文字列。

+0

「Access SQL」のようなものはありません。 AccessはデフォルトでJet SQLを使用しますが、それはAccessから完全に独立しています。 –

+0

真、真。私は自分自身にパンダントポイントをドッキングする:) – mavnn

+0

@mavnn:はい、あなたには恥ずかしい。 *誰も*あなたが何を意味しているかを正確に知っていたという事実は、何にも関係していません:) – onedaywhen

6

次のC#は、.mdbファイルからスキーマを取得する方法の概要を示しています。

データベースへの接続を取得します。

String f = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "database.mdb"; 
OleDbConnection databaseConnection = new OleDbConnection(f); 
databaseConnection.Open(); 

は、各テーブルの名前を取得します。

DataTable dataTable = databaseConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); 
int numTables = dataTable.Rows.Count; 
for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) 
{ 
    String tableName = dataTable.Rows[tableIndex]["TABLE_NAME"].ToString(); 

は、各テーブルのフィールドを取得します。

DataTable schemaTable = databaseConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, tableName, null }); 
    foreach (DataRow row in schemaTable.Rows) 
    { 
     String fieldName = row["COLUMN_NAME"].ToString(); //3 
     String fieldType = row["DATA_TYPE"].ToString(); // 11 
     String fieldDescription = row["DESCRIPTION"].ToString(); //27 
    } 
} 

行います3,11および27はどこから来たのですか?私はデバッガでDataRow.ItemArrayを調べることによってそれらを見つけましたが、誰かが「正しい」方法を知っていますか?

+1

データベース内の各列のフィールド名を取得するには OleDbDataReader。GetName(i)。ここで、iは各フィールドインデックス番号を反復するために使用されます。 OleDbDataReader.GetFieldType(i)は、列のデータ型を返します。 – Stewbob

+0

ああ、私は方法がなければならないことを知っていた!乾杯。 – dukedave

+0

私は答えを、あなたが望む行の実際の文字列値で更新しました。下の回答にすべてのオプションのスクリーンショットを追加します。 – ProVega

2

Compare'Em http://home.gci.net/~mike-noel/CompareEM-LITE/CompareEM.htm 喜んでMDBを再作成する必要があるVBAコードを生成します。または、既存のBE MDBのバージョンアップグレードを行うことができるように、2つのMDB間の相違点を作成するコード。少し気味悪いですが、うまくいきます。新しいACE(Access2007)ACCDB形式はサポートしていないことに注意してください。

私はいつも使っています。

(OneDayWhenの編集は、三分の一正しかったと三分の二が間違っ。)

9

今は古代の質問ですが、残念ながら:(

を多年生私は、このコードは解決策を探して他の人に有用であり得ると思いました。します。cscriptを経由して、コマンドラインから実行するように設計されていないので、あなたのAccessプロジェクトにコードをインポートする必要はありません。と同様に(と触発さ)How do you use version control with Access developmentOliverからコードです。

' Usage: 
' CScript //Nologo ddl.vbs <input mdb file> > <output> 
' 
' Outputs DDL statements for tables, indexes, and relations from Access file 
' (.mdb, .accdb) <input file> to stdout. 
' Requires Microsoft Access. 
' 
' NOTE: Adapted from code from "polite person" + Kevin Chambers - see: 
' http://www.mombu.com/microsoft/comp-databases-ms-access/t-exporting-jet-table-metadata-as-text-119667.html 
' 
Option Explicit 
Dim stdout, fso 
Dim strFile 
Dim appAccess, db, tbl, idx, rel 

Set stdout = WScript.StdOut 
Set fso = CreateObject("Scripting.FileSystemObject") 

' Parse args 
If (WScript.Arguments.Count = 0) then 
    MsgBox "Usage: cscript //Nologo ddl.vbs access-file", vbExclamation, "Error" 
    Wscript.Quit() 
End if 
strFile = fso.GetAbsolutePathName(WScript.Arguments(0)) 

' Open mdb file 
Set appAccess = CreateObject("Access.Application") 
appAccess.OpenCurrentDatabase strFile 
Set db = appAccess.DBEngine(0)(0) 

' Iterate over tables 
    ' create table statements 
For Each tbl In db.TableDefs 
    If Not isSystemTable(tbl) And Not isHiddenTable(tbl) Then 
    stdout.WriteLine getTableDDL(tbl) 
    stdout.WriteBlankLines(1) 

    ' Iterate over indexes 
     ' create index statements 
    For Each idx In tbl.Indexes 
     stdout.WriteLine getIndexDDL(tbl, idx) 
    Next 

    stdout.WriteBlankLines(2) 
    End If 
Next 

' Iterate over relations 
    ' alter table add constraint statements 
For Each rel In db.Relations 
    Set tbl = db.TableDefs(rel.Table) 
    If Not isSystemTable(tbl) And Not isHiddenTable(tbl) Then 
    stdout.WriteLine getRelationDDL(rel) 
    stdout.WriteBlankLines(1) 
    End If 
Next 

Function getTableDDL(tdef) 
Const dbBoolean = 1 
Const dbByte = 2 
Const dbCurrency = 5 
Const dbDate = 8 
Const dbDouble = 7 
Const dbInteger = 3 
Const dbLong = 4 
Const dbDecimal = 20 
Const dbFloat = 17 
Const dbMemo = 12 
Const dbSingle = 6 
Const dbText = 10 
Const dbGUID = 15 
Const dbAutoIncrField = 16 

Dim fld 
Dim sql 
Dim ln, a 

    sql = "CREATE TABLE " & QuoteObjectName(tdef.name) & " (" 
    ln = vbCrLf 

    For Each fld In tdef.fields 
     sql = sql & ln & " " & QuoteObjectName(fld.name) & " " 
     Select Case fld.Type 
     Case dbBoolean 'Boolean 
      a = "BIT" 
     Case dbByte 'Byte 
      a = "BYTE" 
     Case dbCurrency 'Currency 
      a = "MONEY" 
     Case dbDate 'Date/Time 
      a = "DATETIME" 
     Case dbDouble 'Double 
      a = "DOUBLE" 
     Case dbInteger 'Integer 
      a = "INTEGER" 
     Case dbLong 'Long 
      'test if counter, doesn't detect random property if set 
      If (fld.Attributes And dbAutoIncrField) Then 
      a = "COUNTER" 
      Else 
      a = "LONG" 
      End If 
     Case dbDecimal 'Decimal 
      a = "DECIMAL" 
     Case dbFloat  'Float 
      a = "FLOAT" 
     Case dbMemo 'Memo 
      a = "MEMO" 
     Case dbSingle 'Single 
      a = "SINGLE" 
     Case dbText 'Text 
      a = "VARCHAR(" & fld.Size & ")" 
     Case dbGUID 'Text 
      a = "GUID" 
     Case Else 
      '>>> raise error 
      MsgBox "Field " & tdef.name & "." & fld.name & _ 
       " of type " & fld.Type & " has been ignored!!!" 
     End Select 

     sql = sql & a 

     If fld.Required Then _ 
      sql = sql & " NOT NULL " 
     If Len(fld.DefaultValue) > 0 Then _ 
      sql = sql & " DEFAULT " & fld.DefaultValue 

     ln = ", " & vbCrLf 
    Next 

    sql = sql & vbCrLf & ");" 
    getTableDDL = sql 

End Function 

Function getIndexDDL(tdef, idx) 
Dim sql, ln, myfld 

    If Left(idx.name, 1) = "{" Then 
     'ignore, GUID-type indexes - bugger them 
    ElseIf idx.Foreign Then 
     'this index was created by a relation. recreating the 
     'relation will create this for us, so no need to do it here 
    Else 
     ln = "" 
     sql = "CREATE " 
     If idx.Unique Then 
      sql = sql & "UNIQUE " 
     End If 
     sql = sql & "INDEX " & QuoteObjectName(idx.name) & " ON " & _ 
      QuoteObjectName(tdef.name) & "(" 
     For Each myfld In idx.fields 
      sql = sql & ln & QuoteObjectName(myfld.name) 
      ln = ", " 
     Next 
     sql = sql & ")" 
     If idx.Primary Then 
      sql = sql & " WITH PRIMARY" 
     ElseIf idx.IgnoreNulls Then 
      sql = sql & " WITH IGNORE NULL" 
     ElseIf idx.Required Then 
      sql = sql & " WITH DISALLOW NULL" 
     End If 
     sql = sql & ";" 
    End If 
    getIndexDDL = sql 

End Function 

' Returns the SQL DDL to add a relation between two tables. 
' Oddly, DAO will not accept the ON DELETE or ON UPDATE 
' clauses, so the resulting sql must be executed through ADO 
Function getRelationDDL(myrel) 
Const dbRelationUpdateCascade = 256 
Const dbRelationDeleteCascade = 4096 
Dim mytdef 
Dim myfld 
Dim sql, ln 


    With myrel 
     sql = "ALTER TABLE " & QuoteObjectName(.ForeignTable) & _ 
      " ADD CONSTRAINT " & QuoteObjectName(.name) & " FOREIGN KEY (" 
     ln = "" 
     For Each myfld In .fields 'ie fields of the relation 
      sql = sql & ln & QuoteObjectName(myfld.ForeignName) 
      ln = "," 
     Next 
     sql = sql & ") " & "REFERENCES " & _ 
      QuoteObjectName(.table) & "(" 
     ln = "" 
     For Each myfld In .fields 
      sql = sql & ln & QuoteObjectName(myfld.name) 
      ln = "," 
     Next 
     sql = sql & ")" 
     If (myrel.Attributes And dbRelationUpdateCascade) Then _ 
      sql = sql & " ON UPDATE CASCADE" 
     If (myrel.Attributes And dbRelationDeleteCascade) Then _ 
      sql = sql & " ON DELETE CASCADE" 
     sql = sql & ";" 
    End With 
    getRelationDDL = sql 
End Function 


Function isSystemTable(tbl) 
Dim nAttrib 
Const dbSystemObject = -2147483646 
    isSystemTable = False 
    nAttrib = tbl.Attributes 
    isSystemTable = (nAttrib <> 0 And ((nAttrib And dbSystemObject) <> 0)) 
End Function 

Function isHiddenTable(tbl) 
Dim nAttrib 
Const dbHiddenObject = 1 
    isHiddenTable = False 
    nAttrib = tbl.Attributes 
    isHiddenTable = (nAttrib <> 0 And ((nAttrib And dbHiddenObject) <> 0)) 
End Function 

Function QuoteObjectName(str) 
    QuoteObjectName = "[" & str & "]" 
End Function 

あなたはリットルであればクエリ定義をエクスポートすることもできます。this questionが役立ちます。実際には、あなたは(#)

の構文を使用して、通常のDDL CREATE VIEW foo AS ...構文でquerydefsを作成しないため、これは少し異なりますが、ここで私は別々のクエリをバックアップするために書いたスクリプトです。sqlファイル(すべてのフロントエンドdbコードをバックアップするためのより大きなスクリプトの一部です。this questionのOliverの答えを参照してください)。

Dim oApplication 
Set oApplication = CreateObject("Access.Application") 
oApplication.OpenCurrentDatabase sMyAccessFilePath 
oApplication.Visible = False 

For Each myObj In oApplication.DBEngine(0)(0).QueryDefs 
    writeToFile sExportpath & "\queries\" & myObj.Name & ".sql", myObj.SQL 
Next 

Function writeToFile(path, text) 
Dim fso, st 
    Set fso = CreateObject("Scripting.FileSystemObject") 
    Set st = fso.CreateTextFile(path, True) 
    st.Write text 
    st.Close 
End Function 
+0

私が上でコメントしたように、このクエリー定義も含まれていれば素晴らしいでしょう。 – LondonRob

+1

@ロンドンロブ:追加 –

0

非常に役立つ投稿!

SQLサーバー用のデータ定義言語を生成するスクリプトを改訂しました。私はそれが誰かに役立つかもしれないと思ったので、私はそれを共有しています。私が遭遇した1つの問題は、VBSスクリプトがテーブルのすべてのフィールドをインデックス用に抽出することです。私はまだこれを解決する方法がわからないので、最初のフィールドだけを抽出します。これは、ほとんどの主キーで機能します。最後に、すべてのデータ型が証明されているわけではありませんが、私はそれらのほとんどを得ていると思います。

Option Compare Database 


Function exportTableDefs() 

Dim db As Database 
Dim tdf As TableDef 
Dim fld As DAO.Field 
Dim ndx As DAO.Index 
Dim strSQL As String 
Dim strFlds As String 

Dim fs, f 

    Set db = CurrentDb 

    Set fs = CreateObject("Scripting.FileSystemObject") 
    Set f = fs.CreateTextFile("C:\temp\Schema.txt") 

    For Each tdf In db.TableDefs 
     If Left(tdf.Name, 4) <> "Msys" And Left(tdf.Name, 1) <> "~" Then 
      strSQL = "CREATE TABLE [" & tdf.Name & "] (" & vbCrLf 

      strFlds = "" 

      For Each fld In tdf.Fields 

       strFlds = strFlds & ",[" & fld.Name & "] " 

       Select Case fld.Type 

        Case dbText 
         'No look-up fields 
         strFlds = strFlds & "varchar (" & fld.SIZE & ")" 

        Case dbLong 
         If (fld.Attributes And dbAutoIncrField) = 0& Then 
          strFlds = strFlds & "bigint" 
         Else 
          strFlds = strFlds & "int IDENTITY(1,1)" 
         End If 

        Case dbBoolean 
         strFlds = strFlds & "bit" 

        Case dbByte 
         strFlds = strFlds & "tinyint" 

        Case dbInteger 
         strFlds = strFlds & "int" 

        Case dbCurrency 
         strFlds = strFlds & "decimal(10,2)" 

        Case dbSingle 
         strFlds = strFlds & "decimal(10,2)" 

        Case dbDouble 
         strFlds = strFlds & "Float" 

        Case dbDate 
         strFlds = strFlds & "DateTime" 

        Case dbBinary 
         strFlds = strFlds & "binary" 

        Case dbLongBinary 
         strFlds = strFlds & "varbinary(max)" 

        Case dbMemo 
         If (fld.Attributes And dbHyperlinkField) = 0& Then 
          strFlds = strFlds & "varbinary(max)" 
         Else 
          strFlds = strFlds & "?" 
         End If 

        Case dbGUID 
         strFlds = strFlds & "?" 
        Case Else 
         strFlds = strFlds & "?" 

       End Select 
       strFlds = strFlds & vbCrLf 

      Next 

      '' get rid of the first comma 
      strSQL = strSQL & Mid(strFlds, 2) & ")" & vbCrLf 

      f.WriteLine strSQL 

      strSQL = "" 

      'Indexes 
      For Each ndx In tdf.Indexes 

       If Left(ndx.Name, 1) <> "~" Then 
        If ndx.Primary Then 
         strSQL = "ALTER TABLE " & tdf.Name & " ADD CONSTRAINT " & tdf.Name & "_primary" & " PRIMARY KEY CLUSTERED (" & vbCrLf 
        Else 
         If ndx.Unique Then 
          strSQL = "CREATE UNIQUE NONCLUSTERED INDEX " 
         Else 
          strSQL = "CREATE NONCLUSTERED INDEX " 
         End If 
         strSQL = strSQL & "[" & tdf.Name & "_" & ndx.Name & "] ON [" & tdf.Name & "] (" 
        End If 

        strFlds = "" 

        ''' Assume that the index is only for the first field. This will work for most primary keys 
        ''' Not sure how to get just the fields in the index 
        For Each fld In tdf.Fields 
         strFlds = strFlds & ",[" & fld.Name & "] ASC " 
         Exit For 
        Next 

        strSQL = strSQL & Mid(strFlds, 2) & ") " 
       End If 
      Next 
      f.WriteLine strSQL & vbCrLf 
     End If 
    Next 

    f.Close 

End Function 
関連する問題