【问题标题】:Access Listbox query preventing SQL Server Update Query访问列表框查询阻止 SQL Server 更新查询
【发布时间】:2021-03-01 20:13:58
【问题描述】:

我正在同时开发一个 Access 应用程序和一个 SQL Server 后端。我有一个带有列表框的表单,当双击记录时,它会打开一个未绑定的表单并根据所选记录将数据加载到其中。当在第二种形式中进行更改时,一个按钮会启动一个传递查询,该查询执行一个存储过程,更新 SQL Server 中基表中记录的详细信息。

事情就是这样。只要 Form1(带有列表框)打开,存储过程就会超时而不运行。如果我关闭该表格,只需不到一秒钟。当从 Access 运行时、从 Management Studio 运行时以及在 Management Studio 中作为带有硬值的查询(而不是带有参数的存储过程)运行时,它的行为方式都是如此。

列表框的行源是一个链接表,它引用 SQL Server 中的视图。视图中的查询是两个不同表的递归公用表表达式,其中一个是存储过程正在编辑的表。我已将视图设置为只读。还有其他设置可以帮助我吗?

这是存储过程:

PROCEDURE [dbo].[spSalesPlanUpdate]
    @Salesyear numeric(4,0),
    @ItemNumber varchar(20),
    @Baseline int,
    @Speculation int,
    @Comments varchar(max)
AS
declare @SY numeric(4,0),
        @ItN varchar (20),
        @BL int,
        @SPL int,
        @CmT varchar(max)
set @SY = @Salesyear
set @ItN = @ItemNumber
set @BL = @Baseline
set @SPL = @Speculation
set @CmT = @Comments

BEGIN
    SET NOCOUNT ON;


   update SalesPlan
   set Baseline = @BL
        ,Speculation = @SPL
        ,DateModified = getdate()
        ,Comments = @CmT
    where SalesYear = @SY and ItemNumber = @ItN
END

我同时使用了参数和局部变量,因为起初我认为这可能是关于参数嗅探。

这是查询列表框的视图:

view [dbo].[vwSalesPlan] as 
with cte 
as
(
select Item, year(getdate()) as SY
from vwItemsAndLiners il

union all

select ial.Item, 
       (cte.SY + 1)
From vwItemsAndLiners ial join cte on ial.Item  = cte.Item
Where SY < (year(getdate())+ial.YearsFromProp)
)

select sp.ItemNumber, ial.Variety, ial.Size, ial.PerTray, sp.SalesYear, sp.SalesYear - ial.YearsFromProp as PropYear, 
       sp.SalesYear - ial.YearsFromProduction as ProductionYear, 
       sp.Baseline, sp.Speculation, 
       CEILING((CAST(SP.BASELINE AS NUMERIC (12,2)) + CAST(SP.SPECULATION AS numeric(12,2)))/IAL.PerTray)*IAL.PerTray as Total , 
       sp.DateModified, ial.Segment ,'Entered' as [Status], sp.Comments
From SalesPlan sp inner join vwItemsAndLiners ial on sp.ItemNumber = ial.Item
Where ial.status = 'Sell'


union 

select cte.Item, ial.Variety, ial.Size, ial.PerTray, SY, cte.sy - ial.YearsFromProp as PropYear, 
        cte.SY - ial.YearsFromProduction as ProductionYear,'', '', 0, null, ial.Segment , 'Not Entered', null
from cte inner join vwItemsAndLiners ial on cte.Item = ial.Item
where cte.Item not in (select ItemNumber from SalesPlan where salesplan.SalesYear = CTE.SY) and ial.Status = 'Sell'

with check option

正在更新的表:SalesPlan

查看列表框的查询来源:vwSalesPlan

我意识到这里有很多东西。真的,我只是希望这会产生一些想法,说明为什么打开的表单会从更新查询中锁定原始表。谢谢!

【问题讨论】:

  • 访问对于这个来说真的很糟糕,因为它持有打开的锁。不确定您能做些什么
  • 所以在 SSMS 中,当列表框表单打开时,我运行了查询 select * from sys.dm_exec_requests er cross apply sys.dm_exec_sql_text (sql_handle),我返回 2 个会话 ID,其中一个为 ASYNC_NETWORK_IO 等待类型。如果我滚动到列表框的底部,强制访问以读取所有数据,然后再次运行上述脚本,即使列表框表单打开,该会话 ID 也会消失。

标签: sql-server ms-access stored-procedures listbox


【解决方案1】:

我试过了:

  • 在 SQL Server 中为列表框提供行源的视图编制索引,但由于它们包含 CTE,因此无法编制索引。
  • lstbox.recordset.movefirst 然后 lstbox.recordset.movelast 强制访问以读取整个列表,但每当列表被过滤或重新查询时,它都会抛出错误,指出记录集对象已更改并且 movefirst 命令无效。

所以我写了这个子:

Private Sub readtheData()
Dim i As Integer

i = Me.lstSalesPlan.ListCount

End Sub

每次加载表单或过滤列表框后面的查询时,只需强制它对记录进行计数即可强制访问以释放锁定。希望这对未来的人有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    相关资源
    最近更新 更多