在 MS Access 中创建外键 VBA
Create foreign key in MS Access VBA
我有 table tbl0 和 table tbl1。 tbl0 有一个由字段 "Ticker" 组成的主键,我是这样创建的:
Sub CreatPrimaryKey()
Dim db As Database
Set db = CurrentDb
db.Execute "CREATE INDEX TickerID ON tbl0 (Ticker) WITH PRIMARY;"
db.Close
End Sub
...效果很好。
我使用这个确认我有主键:
Sub GetPrimaryKeyField()
Call PrimKey("tbl0")
End Sub
Public Sub PrimKey(tblName As String)
'get primary key of tabel
'how to use: Call PrimKey("tbl_DatedModel_2015_0702_0")
'http://bytes.com/topic/access/answers/679509-finding-primary-key-using-vba
'*******************************************
'Purpose: Programatically determine a
' table's primary key
'Coded by: raskew
'Inputs: from Northwind's debug window:
' Call PrimKey("Products")
'Output: "ProductID"
'*******************************************
Dim db As Database
Dim td As TableDef
Dim idxLoop As Index
Set db = CurrentDb
Set td = db.TableDefs(tblName)
For Each idxLoop In td.Indexes
If idxLoop.Primary = True Then
Debug.Print Mid(idxLoop.Fields, 2)
Exit For
End If
Next idxLoop
db.Close
Set db = Nothing
End Sub
立即数 window 打印 "Ticker"。我不确定 "TickerID" 发生了什么,但无论如何。我得到一个PK。然后我尝试通过这样做在 tbl0 和 tbl1 之间创建外键关系:
Sub CreateForeignKey()Dim db As Database
Set db = CurrentDb
db.Execute "ALTER TABLE tbl1 " _
& "ADD CONSTRAINT fk_tbl1_tbl0 " _
& "FOREIGN KEY (Ticker) REFERENCES tbl0 (Ticker);"
db.Close
End Sub
当我 运行 上面的 sub 我得到错误:
“索引或关系定义中的无效字段定义 "Ticker"”
更新:让这个问题与众不同的部分原因是我在 AlTER TABLE.[=14= 时需要在两个 table 中拥有相同的字段]
您的初始 SQL 语句在字段 "Ticker." 上创建了一个名为 "TickerID" 的索引,这就是调试语句 returns "Ticker" 而不是 "TickerID."
您的外键 SQL 应该是:
ALTER TABLE tbl1 ADD CONSTRAINT fk_tbl1_tbl0
FOREIGN KEY (Ticker) REFERENCES tbl0 (Ticker);
假设您在 tbl1 中有一个名为 "Ticker" 的字段,它与 tbl0.Ticker.
的类型相同
这里的第二行表示您正在创建的外键字段引用了其他 table 中的相关键字段。像这样阅读:table 中的外键 "Ticker" I am altering (tbl1) references the Primary Key "Ticker" in the related table "tbl0".
我使用这个例程,您可能会发现它有帮助。它确实做了一些假设:1) 主键总是命名为 {table_name} + "Id" 和 2) 外键通常命名为相同的东西。 (这两种都是常见的做法,在我看来是可取的)。
Public Function CreateForeignKey( _
db As DAO.Database, _
ByVal sTable As String, _
ByVal sPrimaryTable As String, _
Optional ByVal sField As String) As Boolean
Dim sSQL As String
Dim sSuffix As String
On Error GoTo EH
If sField = "" Then
sField = sPrimaryTable & "Id"
Else
sSuffix = "_" & sField
End If
sSQL = "ALTER TABLE [" & sTable & "]" _
& " ADD CONSTRAINT FK_" & sTable & "_" & sPrimaryTable & sSuffix _
& " FOREIGN KEY([" & sField & "])" _
& " REFERENCES [" & sPrimaryTable & "] ([" & sPrimaryTable & "Id]);"
db.Execute sSQL, dbFailOnError
CreateForeignKey = True
Exit Function
EH:
MsgBox "Error " & Err.Number & vbCrLf _
& " (" & Err.Source & vbCrLf _
& " (" & Err.Description _
& ") in procedure CreateForeignKey of Module Database"
End Function
参考文献:
我认为你的 sql 应该是这样的:
ALTER TABLE tbl1 ADD CONSTRAINT fk_tbl1_tbl0
FOREIGN KEY (TickerId) REFERENCES tbl0 (Ticker);
parentId为tickerID,child为ticker。
可能很旧,但我发现这种语法有效
你想在PK之前指定FK,虽然我不记得为什么在PK中包含FK是个好习惯。
Sub CreateTableJours()
On Error Resume Next
Application.CurrentDb.Execute "Drop Table [Jours];"
'---------------'---------------'
On Error GoTo onError
Dim con As ADODB.Connection
Set con = CurrentProject.Connection
con.Execute "" _
& "CREATE TABLE [Jours](" _
& " [jcode] COUNTER" _
& ",[jdate] DATETIME" _
& ",[tid] INTEGER" _
& ",[cid] INTEGER" _
& ",[jdepense] MONEY" _
& ",[jjustificatif] CHAR" _
& ",CONSTRAINT [FK_Taches] FOREIGN KEY ([tid]) REFERENCES Personnes" _
& ",CONSTRAINT [FK_Chantiers] FOREIGN KEY ([cid]) REFERENCES Chantiers" _
& ",CONSTRAINT [PK_Jours] PRIMARY KEY ([jcode])" _
& ");"
Set con = Nothing
Exit Sub
'---------------'---------------'
onFail:
myErrorLvl = 250
Set con = Nothing
Exit Sub
'---------------'---------------'
onError:
MsgBox Err.Description, , "Erreur(" & myErrorLvl & ") in " & "INIT.CreateTableJours" & "#" & Err.Number
If myErrorLvl < 1 Then Resume onFail
End Sub
我有 table tbl0 和 table tbl1。 tbl0 有一个由字段 "Ticker" 组成的主键,我是这样创建的:
Sub CreatPrimaryKey()
Dim db As Database
Set db = CurrentDb
db.Execute "CREATE INDEX TickerID ON tbl0 (Ticker) WITH PRIMARY;"
db.Close
End Sub
...效果很好。
我使用这个确认我有主键:
Sub GetPrimaryKeyField()
Call PrimKey("tbl0")
End Sub
Public Sub PrimKey(tblName As String)
'get primary key of tabel
'how to use: Call PrimKey("tbl_DatedModel_2015_0702_0")
'http://bytes.com/topic/access/answers/679509-finding-primary-key-using-vba
'*******************************************
'Purpose: Programatically determine a
' table's primary key
'Coded by: raskew
'Inputs: from Northwind's debug window:
' Call PrimKey("Products")
'Output: "ProductID"
'*******************************************
Dim db As Database
Dim td As TableDef
Dim idxLoop As Index
Set db = CurrentDb
Set td = db.TableDefs(tblName)
For Each idxLoop In td.Indexes
If idxLoop.Primary = True Then
Debug.Print Mid(idxLoop.Fields, 2)
Exit For
End If
Next idxLoop
db.Close
Set db = Nothing
End Sub
立即数 window 打印 "Ticker"。我不确定 "TickerID" 发生了什么,但无论如何。我得到一个PK。然后我尝试通过这样做在 tbl0 和 tbl1 之间创建外键关系:
Sub CreateForeignKey()Dim db As Database
Set db = CurrentDb
db.Execute "ALTER TABLE tbl1 " _
& "ADD CONSTRAINT fk_tbl1_tbl0 " _
& "FOREIGN KEY (Ticker) REFERENCES tbl0 (Ticker);"
db.Close
End Sub
当我 运行 上面的 sub 我得到错误: “索引或关系定义中的无效字段定义 "Ticker"”
更新:让这个问题与众不同的部分原因是我在 AlTER TABLE.[=14= 时需要在两个 table 中拥有相同的字段]
您的初始 SQL 语句在字段 "Ticker." 上创建了一个名为 "TickerID" 的索引,这就是调试语句 returns "Ticker" 而不是 "TickerID."
您的外键 SQL 应该是:
ALTER TABLE tbl1 ADD CONSTRAINT fk_tbl1_tbl0
FOREIGN KEY (Ticker) REFERENCES tbl0 (Ticker);
假设您在 tbl1 中有一个名为 "Ticker" 的字段,它与 tbl0.Ticker.
的类型相同这里的第二行表示您正在创建的外键字段引用了其他 table 中的相关键字段。像这样阅读:table 中的外键 "Ticker" I am altering (tbl1) references the Primary Key "Ticker" in the related table "tbl0".
我使用这个例程,您可能会发现它有帮助。它确实做了一些假设:1) 主键总是命名为 {table_name} + "Id" 和 2) 外键通常命名为相同的东西。 (这两种都是常见的做法,在我看来是可取的)。
Public Function CreateForeignKey( _
db As DAO.Database, _
ByVal sTable As String, _
ByVal sPrimaryTable As String, _
Optional ByVal sField As String) As Boolean
Dim sSQL As String
Dim sSuffix As String
On Error GoTo EH
If sField = "" Then
sField = sPrimaryTable & "Id"
Else
sSuffix = "_" & sField
End If
sSQL = "ALTER TABLE [" & sTable & "]" _
& " ADD CONSTRAINT FK_" & sTable & "_" & sPrimaryTable & sSuffix _
& " FOREIGN KEY([" & sField & "])" _
& " REFERENCES [" & sPrimaryTable & "] ([" & sPrimaryTable & "Id]);"
db.Execute sSQL, dbFailOnError
CreateForeignKey = True
Exit Function
EH:
MsgBox "Error " & Err.Number & vbCrLf _
& " (" & Err.Source & vbCrLf _
& " (" & Err.Description _
& ") in procedure CreateForeignKey of Module Database"
End Function
参考文献:
我认为你的 sql 应该是这样的:
ALTER TABLE tbl1 ADD CONSTRAINT fk_tbl1_tbl0
FOREIGN KEY (TickerId) REFERENCES tbl0 (Ticker);
parentId为tickerID,child为ticker。
可能很旧,但我发现这种语法有效 你想在PK之前指定FK,虽然我不记得为什么在PK中包含FK是个好习惯。
Sub CreateTableJours()
On Error Resume Next
Application.CurrentDb.Execute "Drop Table [Jours];"
'---------------'---------------'
On Error GoTo onError
Dim con As ADODB.Connection
Set con = CurrentProject.Connection
con.Execute "" _
& "CREATE TABLE [Jours](" _
& " [jcode] COUNTER" _
& ",[jdate] DATETIME" _
& ",[tid] INTEGER" _
& ",[cid] INTEGER" _
& ",[jdepense] MONEY" _
& ",[jjustificatif] CHAR" _
& ",CONSTRAINT [FK_Taches] FOREIGN KEY ([tid]) REFERENCES Personnes" _
& ",CONSTRAINT [FK_Chantiers] FOREIGN KEY ([cid]) REFERENCES Chantiers" _
& ",CONSTRAINT [PK_Jours] PRIMARY KEY ([jcode])" _
& ");"
Set con = Nothing
Exit Sub
'---------------'---------------'
onFail:
myErrorLvl = 250
Set con = Nothing
Exit Sub
'---------------'---------------'
onError:
MsgBox Err.Description, , "Erreur(" & myErrorLvl & ") in " & "INIT.CreateTableJours" & "#" & Err.Number
If myErrorLvl < 1 Then Resume onFail
End Sub