2017-04-02 61 views
1

我有一個訪問表包含產品信息與100列(這是一個購買的系統,所以不是我的創作)。我希望能夠複製一行並將其插入爲更新了3個字段的新行。我在訪問數據庫上使用VBA。從DAO.Recordset添加一個完整的行到一個表

我正在選擇要複製的行(Select Product。* FROM .....)並將其放入DAO.Recordset中。這工作正常。然後,我希望將這些數據作爲一個新行插入表中,除了產品ID(密鑰)和產品簡短描述之外,所有數據都具有相同的數據。

由於有100列,我試圖避免鍵入所有列名稱和分別賦值。有沒有辦法從DAO.Recordset插入,所以我可以避免輸入所有的列?如果沒有,是否有另一種避免輸入所有列和所有值的方法?這將爲我節省一個非常大的插入語句!

非常感謝

託尼

+0

你看着查詢設計窗口? – Fionnuala

回答

2

可以循環的Fields收集記錄的做到這一點。

如果表結構不時發生變化,那麼這種方法可能更容易被巨大的INSERT語句維護。

如果表格是靜態的,我寧願使用保存的INSERT查詢和參數來修改列。

Sub CopyProductRow() 

    Dim rsSrc As DAO.Recordset 
    Dim rsTgt As DAO.Recordset 
    Dim fld As DAO.Field 
    Dim sFld As String 

    Set rsSrc = CurrentDb.OpenRecordset("SELECT * FROM Products WHERE ProductID = 4711", dbOpenSnapshot) 
    Set rsTgt = CurrentDb.OpenRecordset("Products", dbOpenDynaset, dbAppendOnly) 

    rsTgt.AddNew 

    For Each fld In rsSrc.Fields 
     sFld = fld.Name 
     Select Case sFld 
      ' special cases 
      Case "ProductID": rsTgt(sFld).Value = GetNewProductID() 
           ' or if ProductID is AutoNumber, don't assign anything 
      Case "ProductDesc": rsTgt(sFld).Value = "my new description" 
      ' all other field values are simply copied 
      Case Else: rsTgt(sFld).Value = fld.Value 
     End Select 
    Next fld 

    rsTgt.Update 
    rsTgt.Close 
    rsSrc.Close 

End Sub 
+0

謝謝安德烈。這看起來很完美。我試圖使用這種方法,但我遇到了SQL的問題。我需要傳入產品參考號。我有: SQLStringTable =「SELECT *」&_ 「FROM Product」&_ 「WHERE(Product。[Product Reference] =」&Chr $(39)&ProductReferenceMain&Chr $(39)&「)」 Set rsSrc = db.OpenRecordset(SQLStringTable,dbOpenSnapshot)。 – ag2

+0

我得到一個運行時錯誤'424'所需的對象。任何想法爲什麼SQLStringTable不正確?非常感謝 – ag2

+0

@ ag2:我習慣於擁有一個全局'DB'對象,而不是使用'CurrentDb'(請參閱編輯)。如果SQL不起作用,請參閱[如何在VBA中調試動態SQL](http://stackoverflow.com/a/1099570/3820271),如果仍然不行,請編輯您的問題並添加VBA代碼在那裏。評論中的代碼很難閱讀。 – Andre

0

如果您正試圖將其插回相同的表,那麼你可以不用蒲凌成一個記錄都沒有。

您只需編寫正確的SQL查詢並執行它。

您選擇的數據將是您已經使用更新的值提取的記錄集。

例如:

INSERT INTO tableX(field1, productId, productDesc) 
SELECT field1, 777 as productId, "NewString" as productDesc 
FROM tableX 
WHERE productId=7 

我在評論中提到將遍歷每個字段的建設作爲SQL命令你的字符串的另一種方法,在此執行將是快了很多,然後按記錄處理記錄。 (如插入一個新的產品,用於在訂單表中的每個訂單,其中其他產品已經被訂購,這可能會對訂單的1000個10秒)

'Edited the code supplied by another response above' 
Sub CopyProductRow() 

    Dim sFld, iField, sqlQuery As String 

    i= "INSERT INTO products(" 
    s= "SELECT " 
    w= "WHERE ProductID = 7" 
    For Each fld In rsSrc.Fields 
     Select Case fld.Name 'Check the field name' 
      ' special cases' 
      Case "ProductID": 'If field is Product ID' 
        iFld = "777 as ProductID" '777 will be the product id returned by the select query (therefore inserted)' 
      Case "ProductDesc": 'If field is Product Description ' 
         'The description below will be selected/inserted instead.' 
        iFld = "'New Product Description' as ProductDesc" 
      Case Else: 
        iFld = fld.Name 'No change just select the field and insert as is.' 
     End Select 

     i = i & ", " & fld.Name 
     s = s & ", " & iFld 
    Next fld 

    'Build complete query (removing the first comma in the select statement)' 
    sqlQuery = i & ") " & replace(s, "SELECT ,", "SELECT ") & " " &w 

    'Resulting in a string such as the following' 
    'INSERT INTO products(field1,field2, productId, productDesc, field5, ...)' 
    'SELECT field1, field2, 777 as ProductID, 'New Product Description' as ProductDesc, field5, ...' 
    'FROM tableX' 
    'WHERE productId=7' 

    'Print the query to immediate window 
    Debug.print sqlQuery 

    'Execute the query' 
    currentdb.execute sqlQuery 
End Sub 
+0

您忘了輸入96個其他字段... – Gustav

+0

如果使用SSMS或MS Access構建查詢,則可以複製並粘貼查詢。更改要更改值的字段。 無需輸入全部96個字段。使用上面的DAO.Recordset循環遍歷每個字段時,SQL執行速度會快很多倍。例如,如果您想在訂購其他產品的訂單表中添加產品,則可能會有10,000條記錄。 完成此操作的另一種方法是使用字段名稱上的循環來構建查詢命令文本,然後執行一次。 – ClintB

+0

SQL將不會比DAO更快地複製一條記錄。事實上,如果您使用表單來選擇要複製的記錄,那麼該記錄已經存在於RecordsetClone中。 – Gustav

1

如果您使用的一種形式,你選擇的記錄複製,你也可以使用記錄集

Copy selected record to new record

+0

看起來我已經重新發明了車輪。 :) – Andre

+0

我曾經認爲使用DAO是一種非常普遍的方法,但它仍然會一次又一次地查看笨拙的INSERT INTO ... SELECT代碼的示例。 – Gustav

相關問題