2011-08-01 72 views
0

使用Microsoft VBA中的腳本處理大型平面數據庫並在大約20個不同的表之間進行拆分。該腳本主要包括打開一個表格,檢查平面數據庫中的每一行以確保它不是重複的,然後添加必要的字段。對每個表重複。訪問VBA,未轉義的單引號,替換()和null

我第一次運行它,一切進展順利,直到我試圖處理名稱O'Malley。我認爲很明顯哪裏出了問題。 Google上的快速搜索出現了this related StackOverflow post。我接受了他們的建議,並在將每個字段輸入新表之前添加了Replace(str, "'", "''")。現在我遇到了一個新問題,而Google的幫助不大。

Replace(null, "'", "''")會導致運行時錯誤,並且平面數據庫只會填充空值。我可以添加額外的線之上Replace()調用查看IsNull(),如果這樣就把null到數據庫中,而不是Replace(str, "'", "''"),但我更希望可以放入一個單一的線,如果可能的解決方案。有沒有更好的方法來解決這個難題,或者我需要在我的代碼中使用216 If

編輯 -

另一個原因是我在尋找一個更好的解決方案是我的重複檢查代碼。目前,我有類似如下:

 'Check for duplicates 
     'Assume student is duplicate if it shares: 
     ' (StudentName and School) or SSN 
     Set rstDuplicate = CurrentDb.OpenRecordset("select * from Student where (StudentName = '" & Replace(rstFrom("Student").Value, "'", "''") & "' AND School = '" & Replace(rstFrom("School").Value, "'", "''") & "') OR SSN = '" & Replace(rstFrom("Social").Value, "'", "''") & "'") 
     If rstDuplicate.RecordCount = 0 Then 
      'Duplicate was not found 
      rstTo.AddNew 
      ' Add fields to the new table 
      rstTo.Update 
     End If 

由於Replace()電話是內嵌的重複檢查,如果我改用If語句來檢查null那麼我將不得不要麼保存結果一個字符串或更新到平面數據庫。返回Replace(str, "'", "''")null而不需要額外變量的函數將是理想的。

+0

如果你必須改變216次,你做錯了。你有沒有想過重構檢查功能? – Jacob

+0

另請參見:使用[參數化查詢](http://stackoverflow.com/questions/95277/how-do-you-create-a-parameterized-query-in-ms-access-2003-and-use-other-query -f)來逃避你的數據。 – Jacob

+1

從閱讀你的第一段看來,你正在將你的數據分成20個相同結構的表,這幾乎肯定是一個壞主意。如果您碰到Access的2GB文件大小限制,唯一的原因是很有意義的。當然,在這種情況下,你應該考慮一個不同的數據庫後端。 – mwolfe02

回答

1

如果你想保留一切在線,您可以使用即時如果函數(IIf):

IIf(IsNull(rstFrom("Student").Value), " Is Null", "= " & Replace(rstFrom("Student").Value) 

這將是一個噩夢閱讀和維護,雖然。你最好寫自己的函數來處理比較操作的變化以及撇號轉義:

Function CompFld(Val As Variant) As String 
    If IsNull(Val) Then 
     CompFld = " Is Null " 
    Else 
     CompFld = "= '" & Replace(Val, "'", "''") & "' " 
    End If 
End Function 

使用它作爲這樣:

Dim SQL As String 
SQL = "SELECT * FROM Student " & _ 
     "WHERE (StudentName " & CompFld(rstFrom("Student").Value) & " AND " & _ 
     "  School " & CompFld(rstFrom("School").Value) & ") " & _ 
     " OR (SSN " & CompFld(rstFrom("Social").Value) & ") " 
Set rstDuplicate = CurrentDb.OpenRecordset(SQL) 
If rstDuplicate.RecordCount = 0 Then 
    'Duplicate was not found 
    rstTo.AddNew 
    ' Add fields to the new table 
    rstTo.Update 
End If 
1

一個簡潔,但醜陋的小寶石傳世我從很久以前的事:

Replace(str & "", "'", "''") 

追加一個空字符串爲空值,返回VBA一個空字符串,而不會修改一個非空字符串。

+0

一個名爲'str'的​​變量應該是字符串類型的,所以它不可能是空的。其次,在VBA代碼中,如果要使用長度爲零的字符串連接以使用內置的'vbNullString'常量,那麼效率會更高,因爲已經分配了該內存。這並不重要,但是如果你在一個循環中調用它,它可以產生巨大的性能差異。基本上,絕對不要在VBA代碼中使用'''' - 總是使用'vbNullString'來代替。 –

+0

如果'str'是從數據庫動態獲取的,那麼不能保證它是一個字符串。你可以有一個'text'類型的字段,其中值爲'null'。然後像'CurrentDb.TableDefs(「table」)。Fields(「field」)。Value'這樣的行將返回null。這是我的問題。 – stevendesu

+0

如果您命名變量「str」,那麼這意味着它是字符串類型,並且在Access VBA中,該變量不能爲空。我只是說你的變量名稱會誤導你在這裏完成的任務。當然,如果你的意思是「str」來表示SQL語句中的一個字段,那麼我認爲這是一個更糟糕的名字。我不知道有什麼好的約定,但是替換([Field]&「」,「'」,「''」)'會更清楚地表明原意。 –

1

訪問的數據庫引擎將接受單引號或雙引號作爲查詢中字符串值的分隔符。因此,而不是...

SELECT * FROM Student WHERE StudentName = 'O''Malley' 

...你可以做到這一點...

SELECT * FROM Student WHERE StudentName = "O'Malley" 

這將允許您處理包含撇號輸入。 OTOH,如果您的字符串輸入也包含雙引號,則會中斷。

我懷疑你可能會有更多的事情不只是撇號問題,但我不明白你的大局。您好像爲rstFrom中的每條記錄打開第三個DAO記錄集,以檢查Student表中是否存在匹配項。我會用DCount()代替。

Dim strCriteria As String 
strCriteria = "StudentName = ""O'Malley"" AND School = ""foo""" 
If DCount("*", "Student", strCriteria) = 0 Then 
    'no match found --> add it ' 
End If