传递查询丢失对 SQL 所做的更改
Posted
技术标签:
【中文标题】传递查询丢失对 SQL 所做的更改【英文标题】:Pass-through query losing changes made to SQL 【发布时间】:2014-05-21 13:26:22 【问题描述】:我有一个直通查询MyPassThru
。这是查询 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 所做的更改会回滚。为什么?
【问题讨论】:
【参考方案1】:发生这种情况的原因是持久性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
要进一步解释为什么会发生这种情况,请参阅以下注释较多的测试例程:
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
【讨论】:
以上是关于传递查询丢失对 SQL 所做的更改的主要内容,如果未能解决你的问题,请参考以下文章
DataGrip - 如何查看通过表格编辑器所做的所有更改的历史记录
是否可以编写t-sql脚本来显示最近对数据库行所做的所有更改?
SQL Server 不允许保存更改。您所做的更改要求删除并重新创建以下表。您对无法重新创建的表进行了更改或启用了“阻止保存要求重新创建表的更改”选项