2010-06-07 191 views
0

我很值插入表如果存在,更新,否則插入新記錄

如果記錄存在已經取代它,如果它不存在,然後添加一個新的。

到目前爲止,我有這樣的代碼:

INSERT INTO table_name 
VALUES (value1, value2, value3,...) where pk="some_id"; 

,但我需要像這樣

if not pk="some_id" exists then INSERT INTO table_name 
    VALUES (value1, value2, value3,...) where pk="some_id"; else update table_name where pk="some_id" 

這將是這個正確的SQL語法?

請注意,我使用的SQL訪問,並且我想這可能是VBA和SQL

+3

這可能會幫助你的搜索就知道,這是經常被稱爲「更新插入」。 – DOK 2010-06-07 18:57:15

回答

1

第一次更新您的導入表和主表之間的更新行。

UPDATE table_name AS m 
    INNER JOIN tblImport AS i 
    ON m.pk = i.pk 
SET 
    m.field2 = i.field2, 
    m.field3 = i.field3, 
    m.field4 = i.field4; 

然後添加主表中不存在的任何導入記錄。

INSERT INTO table_name (
    pk, 
    field2, 
    field3, 
    field4) 
SELECT 
    i.pk, 
    i.field2, 
    i.field3, 
    i.field4 
FROM 
    tblImport AS i 
    LEFT JOIN table_name AS m 
    ON i.pk = m.pk 
WHERE 
    (((m.pk) Is Null)); 
+0

嘿你確定(((m.pk)是空));訪問語法?我認爲你必須做ISNULL(東西)「???? – 2010-06-07 19:54:40

+2

可以使用IsNull函數。但是訪問數據庫引擎支持IS NULL和IS NOT在SQL語句中NULL。試試吧!(這爲我工作。) – HansUp 2010-06-07 20:03:48

1

這很容易使用的記錄進行組合。然後代碼將如下所示(對於ADODB記錄集):

myRecordset.find .... 
if myRecordset.EOF then 
    myRecordset.addNew 
endif 
.... 
myRecordset.fields(...) = ... 
.... 
myRecordset.update 
+0

這似乎是太複雜 – 2010-06-07 19:06:28

+0

事實上,它似乎很簡單,因爲它是相當的可編程解決方案的。但是我認爲,對於任何規模的批量記錄來說,效率都會很低。 – 2010-06-09 22:01:38

0

我已經張貼了關於我的方法解決這個問題很多次在許多不同的論壇,但我只是複述我使用的方法的基本結構。儘管如此,沒有辦法一步完成。

  1. 更新來自外部數據源的現有記錄。

  2. 插入不存在的記錄。

這假定可用於現有的表與外部數據源連接的公共主鍵。

任務#2非常簡單,只是不存在的記錄的外連接。

對於#1,可以使用蠻力,爲主鍵以外的每個字段使用SET編寫UPDATE語句,但是我認爲這是凌亂和不必要的。另外,由於我有很多複製的應用程序,我不能這樣做,因爲這會導致錯誤衝突(當字段更新爲與開始時相同的值時)。

因此,爲此,我使用DAO並編寫一個即時SQL語句來更新COLUMN-BY-COLUMN。其基本結構是這樣的:

Dim db As DAO.Database 
    Dim rs As DAO.Recordset 
    Dim fld As DAO.Field 
    Dim strField As String 
    Dim strSet As String 
    Dim strWhere As String 
    Dim strSQL As String 

    Set db = CurrentDB 
    Set rs = db.OpenRecordset("DestinationTable") 
    For Each fld in rs.Fields 
    strField = fld.Name 
    If strField <> "PKField" Then 
     strSet = "DestinationTable." & strField & " = ExternalTable." & strField 
     strWhere = "Nz(DestinationTable." & strField & ",'') = Nz(ExternalTable." & strField & ", '')" 
     strSQL = "UPDATE DestinationTable " 
     strSQL = strSQL & " SET " & strSet 
     strSQL = strSQL & " WHERE " & strWhere 
     db.Execute strSQL, dbFailOnError 
     Debug.Print strField & ": " & db.RecordsAffected 
    End If 
    Next fld 

現在,複雜的部分是處理數字與日期與字符串字段,所以你必須有一定的邏輯寫的WHERE子句使用正確的報價和其他分隔符根據字段類型。而不是測試字段類型,我一般只使用一個情況下,選擇這樣的,使得字符串字段的默認:

Dim strValueIfNull As String 
    Select Case strField 
    Case "DateField1", "DateField2", "NumericField2", "NumericField2", "NumericField3" 
     strValueIfNull = "0" 
    Case Else 
     strValueIfNull = "''" 
     strWhere = "Nz(DestinationTable." & strField & ", '') = Nz(ExternalTable." & strField & ", '')" 
    End Select 
    strWhere = "Nz(DestinationTable." & strField & ", " & strValueIfNull & ") = Nz(ExternalTable." & strField & ", " & strValueIfNull & ")" 

我能有細節有錯,但你的想法,我想。

這意味着,因爲有更新的領域,你會只運行儘可能多的SQL更新,而你只更新需要更新的記錄。如果你還用「最近更新」的日期標記記錄,那麼你應該在UPDATE SQL中這樣做,並且你只想在真正具有不同值的記錄上這樣做。

+0

如果你打算去穿過所有字段循環的麻煩,爲什麼不直接設置的值的每個字段,然後只用一個UPDATE語句上的記錄,而不是執行多發性更新SQL statments的? – JeffO 2010-06-08 13:42:49

+1

呃,我解釋說,兩次:第一次是我經常使用Jet複製並會導致假衝突,二是,如果你需要,杜絕用上次更新日期/時間的記錄,你只希望做它爲*需要*更新記錄。 。 – 2010-06-08 20:03:06

相關問題