| MSDE FunClub |
|
最終更新日 : 2000/11/03 |
|
Microsoft Data Engine FunClub
|
Since 2000.11.03
|
|
SQLServer7.0/MSDE 完全トレーニングテキスト(下巻) |
|
【第22章436p 〜 447p掲載】 |
Option Compare Database
Option Explicit
'
'************************************************************
'
' Access97対応のテーブルに設定された列制約・テーブル制約を調査します
' その結果をストアドプロシージャ呼び出しに作成します
'
' このプログラムは、Access97上で開発しました
'
' このプログラムを、Accessのモジュールシートに読み込んで実行します
'
' (株)日本技術ソフト開発 堀川 明
' http://www.horikawa.ne.jp/msde/
'
'************************************************************
'
'書き込み先テキストファイル名
Const Fname = "D:\Modify.SQL"
'ファイル番号
Dim FNO%
'主キーの列数を記憶
Dim PK_COL%
'主キーの列名を記憶する
Dim PK_NM$(10)
'
Function MKCONSTRAINT()
Dim m%, i%, tbnm$
'ファイルオープン
FNO = FreeFile
Open Fname For Output As #FNO
'テーブル個数(但しアクセスのシステムテーブルを含む)
m = CurrentDb.TableDefs.Count
'TableDefsの添字は 0 から
For i = 0 To m - 1
'テーブルの名前を取得
tbnm$ = CurrentDb.TableDefs(i).Name
'アクセスのシステムテーブルを除く
If Left(tbnm$, 4) <> "MSys" Then
'制約を作成しますか?
If MsgBox(tbnm$ & vbCrLf & "このテーブルの制約を作成しますか?", _
vbYesNo, "制約の作成を行ないますか?") = vbYes Then
'制約の作成
Prt ""
Prt "-- *********************************************"
Prt "-- 【" + tbnm$ & "】テーブルに制約を設定する"
Prt "-- *********************************************"
MakeCONSTRAINT tbnm$
Prt "GO"
End If
End If
Next
'テーブル間の参照整合性の定義を行う
MakeRelation
Close #FNO
MsgBox "制約作成が終了しました", , "終了"
End Function
'
'***********************************************
' テーブルに付けられている制約を調査します
'***********************************************
'
Sub MakeCONSTRAINT(tblnm$)
'主キーの設定"
Search_PrimaryKey tblnm$
'値要求[はい]の設定(NOT NULL)"
Search_NotNull tblnm$
'空文字列の許可[いいえ]の設定(空文字列入力を拒否する)
Search_NotZeroChar tblnm$
'CHECK制約の設定(Accessの式をSQLServerに直してください)
Search_CheckConst tblnm$
'DEFAULT制約の設定(Accessの式をSQLServerに直してください)
Search_DefaultConst tblnm$
'インデックスの設定
Search_Index tblnm$
End Sub
'
'***********************************************
' 主キーの調査を行なう
'***********************************************
'
Sub Search_PrimaryKey(tblnm$)
Dim idx As Index
Dim fd As Field
Dim cn$, i%, sqltp$, header
Dim dbs As Database
Dim tbl As TableDef
header = True
Set dbs = CurrentDb
Set tbl = dbs.TableDefs(tblnm$)
'主キーを構成する列数
PK_COL = 0
'主キー属性のあるインデックスオブジェクトを探す
For Each idx In tbl.Indexes
'主キー属性です
If idx.Primary Then
i = 0
'主キー属性を構成する列は、NOT NULL 属性です
For Each fd In idx.Fields
If header Then
Prt " --主キーの設定"
header = False
End If
'列の名前
PK_NM(i) = fd.Name
'Accessのデータ型をSQLServer型に変換する
AccessTypeToSQL tbl.Fields(PK_NM(i)).Type, tbl.Fields(PK_NM(i)).Size, sqltp$
'主キーを構成する列に NOT NULL 属性を設定
Prt " EXEC ALTTBL_NotNULL '" & tblnm$ & "' , '" & PK_NM(i) & _
"' , '" & sqltp$ & "'"
i = i + 1
Next
'ここでバッチを区切る
'[受注明細]表のとき、ここで区切らないとエラーが発生した
Prt "GO"
PK_COL = i
'主キーは単独ですか?
If i = 1 Then
Prt " EXEC ALTTBL_SetPrimaryKey '" & tblnm$ & _
"' , '" & PK_NM$(0) & "'"
'連結主キーの設定
Else
'制約削除
cn$ = "PK_" & tblnm$ '制約名
Prt " ALTER TABLE " & tblnm$ & " DROP CONSTRAINT " & cn$
'制約の設定
If i = 2 Then
Prt " ALTER TABLE " & tblnm$ & " ADD CONSTRAINT " & cn$ & _
" PRIMARY KEY " & "( " & PK_NM(0) & "," & PK_NM(1) & ")"
ElseIf i = 3 Then
Prt " ALTER TABLE " & tblnm$ & " ADD CONSTRAINT " & cn$ & _
" PRIMARY KEY " & "( " & PK_NM(0) & "," & PK_NM(1) & "," & PK_NM(2) & ")"
ElseIf i = 4 Then
Prt " ALTER TABLE " & tblnm$ & " ADD CONSTRAINT " & cn$ & _
" PRIMARY KEY " & _
"( " & PK_NM(0) & "," & PK_NM(1) & "," & PK_NM(2) & "," & PK_NM(3) & ")"
Else
Prt " 連結に関係する列が5個以上は、設計を見なおした方がいいです"
End If
End If
End If
Next
If Not header Then Prt ""
End Sub
'
'***********************************************
' 値要求[はい]の調査を行なう
'***********************************************
'
Sub Search_NotNull(tblnm$)
Dim colnm$, sqltp$, i%, PFlag, header
Dim dbs As Database
Dim tbl As TableDef
Dim fd As Field
header = True
Set dbs = CurrentDb
Set tbl = dbs.TableDefs(tblnm$)
'テーブルのフィールドを1個1個調査します
For Each fd In tbl.Fields
'フィールドの名前を取得する
colnm$ = fd.Name
'この名前は主キーを構成する列ですか?
PFlag = True
For i = 0 To PK_COL - 1
If colnm$ = PK_NM(i) Then PFlag = False
Next
'値要求が[はい]ですか?
If PFlag And fd.Required Then
If header Then
Prt " --値要求[はい]の設定(NOT NULL)"
header = False
End If
'Accessのデータ型をSQLServer型に変換する
AccessTypeToSQL fd.Type, fd.Size, sqltp$
'ストアドプロシージャの呼び出し文の作成
Prt " EXEC ALTTBL_NotNULL '" & tblnm$ & "' , '" & colnm$ & _
"' , '" & sqltp$ & "'"
End If
Next
If Not header Then Prt ""
End Sub
'
'****************************************************
' 空文字列の許可[いいえ]の設定(空文字列入力を拒否)
'****************************************************
'
Sub Search_NotZeroChar(tblnm$)
Dim colnm$, header
Dim dbs As Database
Dim tbl As TableDef
Dim fd As Field
header = True
Set dbs = CurrentDb
Set tbl = dbs.TableDefs(tblnm$)
'テーブルのフィールドを1個1個調査します
For Each fd In tbl.Fields
'フィールドの名前を取得する
colnm$ = fd.Name
'長さ0の空文字列の入力を拒否しますか?
If (fd.Type = dbText Or fd.Type = dbMemo) And (Not fd.AllowZeroLength) Then
'Check制約は、データ型によっては、設定できない
If DoCheck(fd) Then
If header Then
Prt " --空文字列の許可[いいえ]の設定(空文字列入力を拒否する)"
header = False
End If
'ストアドプロシージャの呼び出し文の作成
Prt " EXEC ALTTBL_SetCHECK '" & tblnm$ & "' , '" & colnm$ & _
"' , '" & colnm$ & " <> '''' '"
End If
End If
Next
If Not header Then Prt ""
End Sub
'
'****************************************************
' CHECK制約式の設定
' Accessの式をSQLServer用に後で変換してください
'****************************************************
'
Sub Search_CheckConst(tblnm$)
Dim colnm$, header
Dim dbs As Database
Dim tbl As TableDef
Dim fd As Field
header = True
Set dbs = CurrentDb
Set tbl = dbs.TableDefs(tblnm$)
'テーブルのフィールドを1個1個調査します
For Each fd In tbl.Fields
'フィールドの名前を取得する
colnm$ = fd.Name
'ValidationRule プロパティを調べる
If fd.ValidationRule <> "" Then
If header Then
Prt " --CHECK制約の設定(Accessの式をSQLServerに直してください)"
header = False
End If
'ストアドプロシージャの呼び出し文の作成
Prt " EXEC ALTTBL_SetCHECK '" & tblnm$ & "' , '" & colnm$ & _
"' , '*** " & fd.ValidationRule & " ***'"
End If
Next
If Not header Then Prt ""
End Sub
'
'****************************************************
' CHECK制約を実行できますか?
' 実行できるものは TRUE を返す
' Text型の場合は、設定ができません
'****************************************************
'
Function DoCheck(fd As Field) As Boolean
Dim sqltp$
DoCheck = True
'Accessのデータ型をSQLServer型に変換する
AccessTypeToSQL fd.Type, fd.Size, sqltp$
If sqltp$ = "Text" Then
Prt "-- " & fd.Name & "列は、Text型のため、CHECK制約式の設定ができませんでした"
DoCheck = False
End If
End Function
'
'****************************************************
' DEFAULT制約式の設定
' Accessの式をSQLServer用に後で変換してください
'****************************************************
'
Sub Search_DefaultConst(tblnm$)
Dim colnm$, header
Dim dbs As Database
Dim tbl As TableDef
Dim fd As Field
header = True
Set dbs = CurrentDb
Set tbl = dbs.TableDefs(tblnm$)
'テーブルのフィールドを1個1個調査します
For Each fd In tbl.Fields
'フィールドの名前を取得する
colnm$ = fd.Name
'DefaultValue プロパティを調べる
If fd.DefaultValue <> "" Then
If header Then
Prt " --DEFAULT制約の設定(Accessの式をSQLServerに直してください)"
header = False
End If
'ストアドプロシージャの呼び出し文の作成
Prt " EXEC ALTTBL_SetDEFAULT '" & tblnm$ & "' , '" & colnm$ & _
"' , '*** " & fd.DefaultValue & " ***'"
End If
Next
If Not header Then Prt ""
End Sub
'
'***********************************************
' インデックスの調査を行なう
'***********************************************
'
Sub Search_Index(tblnm$)
Dim idx As Index
Dim fd As Field
Dim cn$, i%, sqltp$, NM$(10), header, fg%
Dim dbs As Database
Dim tbl As TableDef
header = True
Set dbs = CurrentDb
Set tbl = dbs.TableDefs(tblnm$)
'インデックスオブジェクトを探す
For Each idx In tbl.Indexes
'主キー属性と外部キー属性は除くこと
If (Not idx.Primary) And (Not idx.Foreign) Then
If header Then
Prt " --インデックスの作成(フラグ 0=重複あり 1=UNIQUE)"
header = False
End If
i = 0
'インデックスを構成する列名に取得
For Each fd In idx.Fields
'列の名前
NM(i) = fd.Name
i = i + 1
Next
'Normal or Unique?
fg% = 0
If idx.Unique Then fg% = 1
'単独ですか?
If i = 1 Then
Prt " EXEC ALTTBL_MakeIDX '" & tblnm$ & _
"' , '" & NM$(0) & "' , " & fg%
'連結主キーの設定
Else
'制約削除
cn$ = "IX_" & tblnm$ '制約名
Prt " ALTER TABLE " & tblnm$ & " DROP CONSTRAINT " & cn$
'制約の設定
If i = 2 Then
Prt " CREATE " & IIf(fg% = 0, "", "UNIQUE") & " INDEX " & cn$ & _
" ON " & tblnm$ & " ( " & NM(0) & "," & NM(1) & ")"
ElseIf i = 3 Then
Prt " CREATE " & IIf(fg% = 0, "", "UNIQUE") & " INDEX " & cn$ & _
" ON " & tblnm$ & " ( " & NM(0) & "," & NM(1) & "," & NM(2) & ")"
ElseIf i = 4 Then
Prt " CREATE " & IIf(fg% = 0, "", "UNIQUE") & " INDEX " & cn$ & _
" ON " & tblnm$ & " ( " & NM(0) & "," & NM(1) & "," & NM(2) & "," & NM(3) & ")"
Else
Prt " 連結に関係する列が5個以上は、設計を見なおした方がいいです"
End If
End If
End If
Next
If Not header Then Prt ""
End Sub
'
'***********************************************
' テーブル間の参照整合性制約を作成する
'***********************************************
'
Sub MakeRelation()
Dim total%, fm$
Dim dbs As Database
Dim rel As Relation
Set dbs = CurrentDb
'リレーションの個数
total = dbs.Relations.Count
If total = 0 Then Exit Sub
Prt ""
Prt "-- **************************************************"
Prt "-- 【参照整合性制約の設定】 "
Prt " -- ALTTBL_SetRelation 主キーTable , 主キー列名 , "
Prt " -- 外部キーTable , 外部キー列名 "
Prt "-- ***************************************************"
fm$ = "!@@@@@@@@@@@@@@@@"
For Each rel In dbs.Relations
Prt " EXEC ALTTBL_SetRelation " & _
Format$("'" + rel.Table + "'", fm$) & "," & _
Format$("'" + rel.Fields(0).Name + "'", fm$) & "," & _
Format$("'" + rel.ForeignTable + "'", fm$) & "," & _
Format$("'" + rel.Fields(0).ForeignName + "'", fm$)
Next
Prt "GO"
End Sub
'
'******************
' メッセージの出力
'******************
'
Sub Prt(msg$)
'Debug.Print msg$
Print #FNO, msg$
End Sub
'
'*************************************************************
' アクセスのデータ型宣言からSQLServerのデータ型宣言に変換します
'*************************************************************
'
Sub AccessTypeToSQL(actp%, acsz%, sqltp$)
'データ型の取得
Select Case actp%
Case dbBoolean 'ブール型 (Boolean)
sqltp$ = "Bit"
Case dbByte 'バイト型 (Byte)
sqltp$ = "Tinyint"
Case dbChar 'CHAR 型 (Char)
sqltp$ = "VARCHAR(" & acsz% & ")"
Case dbCurrency '通貨型 (Currency)
sqltp$ = "Money"
Case dbDate '日付 / 時刻型(Date / Time)
sqltp$ = "DATETIME"
Case dbDouble '倍精度浮動小数点数型 (Double)
sqltp$ = "FLOAT"
Case dbInteger '整数型 (Integer)
sqltp$ = "SMALLINT"
Case dbLong '長整数型 (Long)
sqltp$ = "INT"
Case dbLongBinary 'ロング バイナリ型 (LongBinary) - OLE オブジェクト型 (OLE Object)
sqltp$ = "IMAGE"
Case dbMemo 'メモ型(Memo)
sqltp$ = "Text"
Case dbSingle '単精度浮動小数点数型 (Single)
sqltp$ = "Real"
Case dbText 'テキスト型(Text)
sqltp$ = "VARCHAR(" & acsz% & ")"
Case dbTime '時刻型(Time)
sqltp$ = "Datetime"
Case dbTimeStamp 'タイムスタンプ型(TimeStamp)
sqltp$ = "timestamp"
Case dbVarBinary '可変長バイナリ型(VarBinary)
sqltp$ = "varbinary(" & acsz% & ")"
End Select
End Sub