2014-04-08 30 views
2

我有一個傳遞查詢MyPassThru。這是查詢的SQL的簡化版本:傳遞查詢失去對SQL所做的更改

SET NOCOUNT ON 

DECLARE @FromDate datetime = '1/25/2014' 
DECLARE @ThruDate datetime = '3/1/2014' 

SELECT * 
    FROM MtgDailyTrans M 
    WHERE M.TransDate >= @FromDate 
    AND M.TransDate <= @ThruDate 

我需要更改@FromDate和@ThruDate參數。我寫了下面的函數來做到這一點(source for RegExReplace):

Private gDb As DAO.Database 

Function Db() As DAO.Database 
    If gDb Is Nothing Then Set gDb = CurrentDb 
    Set Db = gDb 
End Function 

Sub MyPassThruSetDates(FromDate As Date, ThruDate As Date) 
    Const FromPattern As String = "(@FromDate datetime = ')([\d/]+)'" 
    Const ThruPattern As String = "(@ThruDate datetime = ')([\d/]+)'" 
    Dim qd As DAO.QueryDef 
    Set qd = Db.QueryDefs("MyPassThru") 
    qd.SQL = RegExReplace(FromPattern, qd.SQL, "$1" & Format(FromDate, "m/d/yyyy") & "'") 
    qd.SQL = RegExReplace(ThruPattern, qd.SQL, "$1" & Format(ThruDate, "m/d/yyyy") & "'") 
    Set qd = Nothing 
End Sub 

的問題是,當我爲MyPassThru更改SQL,然後運行MyPassThruSetDates()過程中,我對SQL所做的更改都會回滾。爲什麼?

回答

2

發生這種情況的原因是,持久Db對象被緩存的QueryDef和它的屬性(也包括.SQL屬性)的副本。如果您致電MyPassThruSetDates,然後對MyPassThru進行SQL更改,然後再次調用MyPassThruSetDates,則原始SQL將覆蓋從原始調用至MyPassThruDates以來所做的任何更改。

解決方案是刷新QueryDefs集合,以確保它使用的是最新的值:

Sub MyPassThruSetDates(FromDate As Date, ThruDate As Date) 
    Const FromPattern As String = "(@FromDate datetime = ')([\d/]+)'" 
    Const ThruPattern As String = "(@ThruDate datetime = ')([\d/]+)'" 
    Dim qd As DAO.QueryDef 
    Db.QueryDefs.Refresh ' <--- This is the key!!! 
    Set qd = Db.QueryDefs("MyPassThru") 
    qd.SQL = RegExReplace(FromPattern, qd.SQL, "$1" & Format(FromDate, "m/d/yyyy") & "'") 
    qd.SQL = RegExReplace(ThruPattern, qd.SQL, "$1" & Format(ThruDate, "m/d/yyyy") & "'") 
    Set qd = Nothing 
End Sub 

對於爲什麼出現這種情況進一​​步說明,請參考以下heavily-評論測試例程:

Sub TestDbCache() 
    Const QName As String = "TempQry" 

    Dim qd As DAO.QueryDef, db As DAO.Database 

    'First, we create a querydef 
    Set db = CurrentDb 
    Set qd = db.CreateQueryDef(QName, "SELECT 'original'") 
    Debug.Print qd.SQL       '--> SELECT 'original'; 

    'Next, we update the querydef's .SQL outside the scope of our db object 
    CurrentDb.QueryDefs(QName).SQL = "SELECT 'changed'" 

    'The querydef and db objects are unaware of the change to .SQL 
    Debug.Print qd.SQL       '--> SELECT 'original'; 
    Debug.Print db.QueryDefs(QName).SQL   '--> SELECT 'original'; 
    Debug.Print CurrentDb.QueryDefs(QName).SQL '--> SELECT 'changed'; 

    'Refreshing the collection updates both the db and qd objects 
    db.QueryDefs.Refresh 
    Debug.Print qd.SQL       '--> SELECT 'changed'; 
    Debug.Print db.QueryDefs(QName).SQL   '--> SELECT 'changed'; 

    'Note that the .SQL is "SELECT 'changed'" when we set the NewDb object 
    Dim NewDb As DAO.Database 
    Set NewDb = CurrentDb 

    'We change the .SQL without refreshing the NewDb's QueryDefs collection 
    CurrentDb.QueryDefs(QName).SQL = "SELECT 'changed again'" 

    'Since the NewDb object never cached the contents of the query, 
    ' it returns the correct current value of .SQL 
    Debug.Print NewDb.QueryDefs(QName).SQL  '--> SELECT 'changed again'; 

    'The other db object has not refreshed its QueryDefs collection, 
    ' so it is wrong once again 
    Debug.Print qd.SQL       '--> SELECT 'changed'; 
    Debug.Print db.QueryDefs(QName).SQL   '--> SELECT 'changed'; 
End Sub