【问题标题】:Create foreign key in MS Access VBA在 MS Access VBA 中创建外键
【发布时间】:2015-07-07 19:22:40
【问题描述】:

我有表 tbl0 和表 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

即时窗口打印“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”无效”

更新:这个问题的不同之处在于我遇到的问题的一部分是,当我更改表时,我需要在两个表中拥有相同的字段。

【问题讨论】:

  • 除了我完全按照 HansUp 在他的回答中建议的那样做(至少看起来我是这样)。我已经看过那个问题/答案了。我错过了什么?
  • 您确认 tbl1 包含一个名为 Ticker 的字段吗?
  • 你好汉斯普! Don J. 刚刚谈到了这一点。我正在整理如何添加它。

标签: sql vba ms-access ms-access-2013


【解决方案1】:

您的初始 SQL 语句在“Ticker”字段上创建一个名为“TickerID”的索引。这就是调试语句返回“Ticker”而不是“TickerID”的原因。

您的外键 SQL 应该是:

ALTER TABLE tbl1 ADD CONSTRAINT fk_tbl1_tbl0 
FOREIGN KEY (Ticker) REFERENCES tbl0 (Ticker);

这假设您在 tbl1 中有一个名为“Ticker”的字段,它与 tbl0.Ticker 的类型相同。

这里的第二行表示您正在创建的外键字段引用另一个表中的相关键字段。像这样阅读:我正在更改的表 (tbl1) 中的外键“Ticker”引用了相关表“tbl0”中的主键“Ticker”。

我使用此例程,您可能会发现它很有帮助。它确实做了一些假设: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

参考文献:

【讨论】:

  • 我在索引或关系的定义中得到“无效的字段定义“TickerID”。我也尝试了“Ticker”而不是“TickerID”并得到了类似的错误。
  • 现在看看。这解释了 SQL 语句在做什么以及哪些部分是什么。解密 SQL 语句并使用您的实际字段名称应用。他们可能都是“Ticker”
  • 嗯。所以你说我必须在使用你的SQL之前将字段“Ticker”添加到tbl1,对吧?我会试着弄清楚如何做到这一点,然后回到这里......
  • 是的。始终在现有字段上创建外键约束。您在外部表中至少有一个字段(约束所在的字段)和相关表中的至少一个键(主键所在的字段)。
  • 出于好奇,你为什么要在代码中做这一切?这是要重复和动态的事情吗?如果没有,您最好使用 GUI 来创建这些。它还将帮助您更好地理解它们。
【解决方案2】:

我认为你的 sql 应该是这样的:

 ALTER TABLE tbl1 ADD CONSTRAINT fk_tbl1_tbl0 
FOREIGN KEY (TickerId) REFERENCES tbl0 (Ticker);

parentId 是tickerID,孩子是ticker。

【讨论】:

  • 当我尝试这样做时,我得到“invalid field definition "TickerID" in definition of index or relationthip”。
【解决方案3】:

也许老了,但我发现这种语法可以工作 您想在 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多