web-dev-qa-db-ja.com

最後に挿入された行の自動番号値-MS Access / VBA

主キーとして自動番号を持つJETテーブルがあり、行を挿入した後にこの番号を取得する方法を知りたいです。 MAX()を使用して最高値を持つ行を取得することを考えましたが、これがどの程度信頼できるかはわかりません。いくつかのサンプルコード:

_Dim query As String
Dim newRow As Integer
query = "INSERT INTO InvoiceNumbers (date) VALUES (" & NOW() & ");"
newRow = CurrentDb.Execute(query)
_

Execute()は主キーの値を返さないため、これは機能しないことがわかりましたが、これは基本的に私が探している種類のコードです。別のテーブルの行の数を更新するには、新しい行の主キーを使用する必要があります。

これを行う最も簡単で最も読みやすい方法は何ですか?

35
a_m0d

DAOを使用する場合

RS.Move 0, RS.LastModified
lngID = RS!AutoNumberFieldName

ADOを使用する場合

cn.Execute "INSERT INTO TheTable.....", , adCmdText + adExecuteNoRecords
Set rs = cn.Execute("SELECT @@Identity", , adCmdText)
Debug.Print rs.Fields(0).Value

cnは有効なADO接続、@@Identityは、この接続に最後に挿入されたIdentity(オートナンバー)を返します。

ご了承ください @@Identityは、最後に生成された値が関心のある値ではない可能性があるため、面倒な場合があります。Accessデータベースエンジンの場合、VIEWプロパティを持つ2つのテーブルを結合するIDENTITYあなたも INSERT INTO the VIEW。 SQL Serverの場合、IDENTITYプロパティも持つ別のテーブルにレコードを挿入するトリガーがあるかどうかを検討してください。

BTW DMaxは、誰かがレコードを挿入した直後にDmax関数が実行を終了する前に他の誰かがレコードを挿入するようには機能しません。

37
Tony Toews

この例では、CurrentDBを使用してINSERTを実行しているため、自分で作成するのが難しくなりました。代わりに、これは動作します:

  Dim query As String
  Dim newRow As Long  ' note change of data type
  Dim db As DAO.Database

  query = "INSERT INTO InvoiceNumbers (date) VALUES (" & NOW() & ");"
  Set db = CurrentDB
  db.Execute(query)
  newRow = db.OpenRecordset("SELECT @@IDENTITY")(0)
  Set db = Nothing

以前はAddOnlyレコードセットを開いてそこからIDを取得することでINSERTを実行していましたが、これははるかに効率的です。また、ADOを必要としないことに注意してください。

47
David-W-Fenton

これはあなたのための私のコードからの適応です。私は developpez.com からインスピレーションを受けました(次のページをご覧ください: "Pourinsérerdesdonnées、vaut-il mieux passer par un RecordSet or par unerequêtede type INSERT? ")。彼らは(少しフランス語で)説明します。この方法は、上の方法よりもはるかに高速です。例では、この方法は37倍高速でした。それを試してみてください。

Const tableName As String = "InvoiceNumbers"
Const columnIdName As String = "??"
Const columnDateName As String = "date"

Dim rsTable As DAO.recordSet
Dim recordId as long

Set rsTable = CurrentDb.OpenRecordset(tableName)
Call rsTable .AddNew
recordId = CLng(rsTable (columnIdName)) ' Save your Id in a variable
rsTable (columnDateName) = Now()        ' Store your data
rsTable .Update

recordSet.Close

ルシグネ

5
LeCygne
Private Function addInsert(Media As String, pagesOut As Integer) As Long


    Set rst = db.OpenRecordset("tblenccomponent")
    With rst
        .AddNew
        !LeafletCode = LeafletCode
        !LeafletName = LeafletName
        !UNCPath = "somePath\" + LeafletCode + ".xml"
        !Media = Media
        !CustomerID = cboCustomerID.Column(0)
        !PagesIn = PagesIn
        !pagesOut = pagesOut
        addInsert = CLng(rst!enclosureID) 'ID is passed back to calling routine
        .Update
    End With
    rst.Close

End Function
3
Derek Ebrey

すぐ上の例は両方ともうまくいきませんでした。テーブルのレコードセットを開いてレコードを追加すると、次の場合を除き、レコードを追加できます。

myLong = CLng(rs!AutoNumberField)

rs.AddNewとrs.Updateの間に配置すると、Nullを返します。 rs.Updateの後に置くと、何かを返しますが、常に間違っており、常に同じ誤った値を返します。新しいレコードを追加した直後にテーブルを見ると、上記のステートメントで返された値とは異なる自動番号フィールド値が表示されます。

myLong = DLookup("AutoNumberField","TableName","SomeCriteria")

rs.Updateの後に行われ、レコードを一意に識別できる他のフィールドがある限り、適切に機能します。

0
RMittelman