我一直试图将这个问题调试好几个小时。在VBA中执行SQL Server存储过程时,出现以下错误:运行时错误' -2147217871'查询超时已过期。重要的是要记住它已经工作了几个星期,直到两天前没有问题。
我已经尝试在命令级别更改VBA代码中的timeout参数但没有成功。存储过程在大约12秒内在SQL Server中执行得很好。
我的vba代码如下:
Sub perfAttrib()
' Variables
Dim con As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim qryPos, qryAst As String
con.ConnectionTimeout = 0
Application.ScreenUpdating = False
shtPerf.Columns("A:T").ClearContents
' Select date
con.Open "Provider=SQLOLEDB;Data Source=DOM-SRV02;Initial Catalog=dbPam;Integrated Security=SSPI;"
' ===================================== Get positions ==========================================
' Set up the connection
Set rs = New ADODB.Recordset
Set cmd = New ADODB.Command
cmd.ActiveConnection = con
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "dbo.prcPnL"
Dim clientPort As String
Dim portfolioNb As String
cmd.Parameters.Refresh
cmd.Parameters(1).Value = shtPerfAttrib.Range("cPerfAttribCcy").Text
cmd.Parameters(2).Value = shtPerfAttrib.Range("cPerfAttribStartDate").Text
cmd.Parameters(3).Value = shtPerfAttrib.Range("cPerfAttribEndDate").Text
clientPort = shtPerfAttrib.Range("cPerfPortfolio").Text
portfolioNb = VBA.Right(clientPort, 16)
cmd.Parameters(4).Value = portfolioNb
Set rs = cmd.Execute
If rs.EOF And rs.BOF Then
MsgBox ("The position query did not return any results.")
Exit Sub
End If
shtPerf.Activate
' Add headers in the sheet
For i = 0 To rs.Fields.Count - 1
shtPerf.Cells(2, i + 1) = rs.Fields(i).Name
Next
shtPerf.Cells(3, 1).CopyFromRecordset rs
shtPerfAttrib.Activate
Application.OnTime Now + TimeValue("00:00:03"), "refreshPivot"
End Sub
我的程序非常复杂,看起来像这样:
USE [dbPam]
GO
/****** Object: StoredProcedure [dbo].[prcPnL] Script Date: 3/4/2015 9:50:50 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[prcPnL]
-- Add the parameters for the stored procedure here
@ccy nvarchar(3),
@startDate nvarchar(50) ,
@endDate nvarchar(50),
@portfolio nvarchar(100)
-- <@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>,
-- <@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
--SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
SELECT subQuery.colCodeClient, @ccy as perfCcy, subQuery.colBankRelNb, subQuery.bankRelCcy, subQuery.colPortfolioNb, subQuery. portCcy, subQuery.colDepNb, subQuery.depCcy, subQuery.colId, subQuery.colName,subQuery.colTickerBB, subQuery.colISIN, subQuery.colAssetClass, subQuery.instrCcy , startDate, endDate, (tblDatPos.colLots ) as [finalLots], posPrev.colMktPrice as [begPrice] , tblDatPos.colMktPrice as [finaltMktPrice], PnL
FROM
(SELECT tblDefBankRel.colCodeClient, tblDefBankRel.colBankRelNb ,tblDefBankRel.colCcy as bankRelCcy, tblDefPortfolio.colPortfolioNb,tblDefPortfolio.colCcy as portCcy, TabPrev.colDepNb, tblDefDep.colCcy as depCcy, TabPrev.colId, tblDefSecu.colName, tblDefSecu.colTickerBB, tblDefSecu.colISIN, tblDefSecu.colAssetClass, tblDefSecu.colCcy as instrCcy, min(TabPrev.PrevDate) as startDate, max(TabPrev.colDate) as endDate, sum((TabPrev.colMktPrice-dbPam.dbo.tblDatPos.colMktPrice)*tblDatPos.colLots) AS [locPnL] , sum((TabPrev.colMktPrice*currFX.colValue-dbPam.dbo.tblDatPos.colMktPrice*prevFX.colValue)*tblDatPos.colLots) AS [PnL]
FROM (SELECT dbPam.dbo.tblDatPos.colDepNb, dbPam.dbo.tblDatPos.colId, dbPam.dbo.tblDatPos.colDate, Max(Tab_1.colDate) AS PrevDate, dbPam.dbo.tblDatPos.colMktPrice
FROM dbPam.dbo.tblDatPos
INNER JOIN dbPam.dbo.tblDatPos AS Tab_1 ON (dbPam.dbo.tblDatPos.colId = Tab_1.colId) AND (dbPam.dbo.tblDatPos.colDepNb = Tab_1.colDepNb) AND (dbPam.dbo.tblDatPos.colDate > Tab_1.colDate)
WHERE dbPam.dbo.tblDatPos.colDate BETWEEN @startDate AND @endDate
GROUP BY dbPam.dbo.tblDatPos.colId, tblDatPos.colDate, tblDatPos.colDepNb, tblDatPos.colMktPrice) AS TabPrev
INNER JOIN dbPam.dbo.tblDatPos ON (TabPrev.colId = tblDatPos.colId) AND (TabPrev.PrevDate=tblDatPos.colDate) AND (TabPrev.colDepNb=tblDatPos.colDepNb)
INNER JOIN dbPam.dbo.tblDefDep ON tblDefDep.colDepNb=tblDatPos.colDepNb
INNER JOIN dbPam.dbo.tblDefPortfolio ON tblDefPortfolio.colPortfolioNb = tblDefDep.colPortfolioNb
INNER JOIN dbPam.dbo.tblDefBankRel ON tblDefBankRel.colBankRelNb=tblDefPortfolio.colBankRelNb
INNER JOIN dbProd.dbo.tblDefSecu ON tblDefSecu.colId = tblDatPos.colId
INNER JOIN dbMktData.dbo.tblDatFX as prevFX ON (prevFX.colCcy1 = tblDefSecu.colCcy ) AND (prevFX.colCcy2 = @ccy) AND (TabPrev.PrevDate=prevFX.colDate)
INNER JOIN dbMktData.dbo.tblDatFX as currFX ON (currFX.colCcy1 = tblDefSecu.colCcy ) AND (currFX.colCcy2 = @ccy) AND (TabPrev.colDate=currFX.colDate)
WHERE dbPam.dbo.tblDatPos.colType = 'TRAD' and tblDefPortfolio.colPortfolioNb = @portfolio and prevFX.colType = 'Bbg' and currFX.colType = 'Bbg'
GROUP BY tblDefBankRel.colCodeClient, tblDefBankRel.colBankRelNb ,tblDefBankRel.colCcy , tblDefPortfolio.colPortfolioNb,tblDefPortfolio.colCcy , TabPrev.colDepNb, tblDefDep.colCcy , TabPrev.colId, tblDefSecu.colName, tblDefSecu.colTickerBB, tblDefSecu.colISIN, tblDefSecu.colAssetClass, tblDefSecu.colCcy ) as subQuery
INNER JOIN dbPam.dbo.tblDatPos ON tblDatPos.colId = subQuery.colId AND tblDatPos.colDate = subQuery.endDate AND tblDatPos.colDepNb = subQuery.colDepNb
INNER JOIN dbPam.dbo.tblDatPos AS posPrev ON posPrev.colId = subQuery.colId AND posPrev.colDate = subQuery.startDate AND posPrev.colDepNb = subQuery.colDepNb
WHERE tblDatPos.colType = 'TRAD' and posPrev.colType = 'TRAD'
--ORDER BY colCodeClient desc
UNION all
SELECT subQuery.colCodeClient,@ccy as perfCcy, subQuery.colBankRelNb, subQuery.bankRelCcy, subQuery.colPortfolioNb, subQuery. portCcy, subQuery.colDepNb, subQuery.depCcy, subQuery.colId, subQuery.colName,'', '', 'Other', subQuery.instrCcy , startDate, endDate, tblDatPos.colLots as [finalLots], posPrev.colMktPrice as [begPrice] , tblDatPos.colMktPrice as [finaltMktPrice], PnL
FROM
(SELECT tblDefBankRel.colCodeClient, tblDefBankRel.colBankRelNb ,tblDefBankRel.colCcy as bankRelCcy, tblDefPortfolio.colPortfolioNb,tblDefPortfolio.colCcy as portCcy, TabPrev.colDepNb, tblDefDep.colCcy as depCcy, TabPrev.colId, tblDefOther.colName, '' as colTickerBB, '' as colISIN, 'Other' as colAssetClass, tblDefOther.colCcy as instrCcy, min(TabPrev.PrevDate) as startDate, max(TabPrev.colDate) as endDate, sum((TabPrev.colMktPrice-dbPam.dbo.tblDatPos.colMktPrice)*tblDatPos.colLots) AS [locPnL] , sum((TabPrev.colMktPrice*currFX.colValue-dbPam.dbo.tblDatPos.colMktPrice*prevFX.colValue)*tblDatPos.colLots) AS [PnL]
FROM (SELECT dbPam.dbo.tblDatPos.colDepNb, dbPam.dbo.tblDatPos.colId, dbPam.dbo.tblDatPos.colDate, Max(Tab_1.colDate) AS PrevDate, dbPam.dbo.tblDatPos.colMktPrice
FROM dbPam.dbo.tblDatPos
INNER JOIN dbPam.dbo.tblDatPos AS Tab_1 ON (dbPam.dbo.tblDatPos.colId = Tab_1.colId) AND (dbPam.dbo.tblDatPos.colDepNb = Tab_1.colDepNb) AND (dbPam.dbo.tblDatPos.colDate > Tab_1.colDate)
WHERE dbPam.dbo.tblDatPos.colDate BETWEEN @startDate AND @endDate
GROUP BY dbPam.dbo.tblDatPos.colId, tblDatPos.colDate, tblDatPos.colDepNb, tblDatPos.colMktPrice) AS TabPrev
INNER JOIN dbPam.dbo.tblDatPos ON (TabPrev.colId = tblDatPos.colId) AND (TabPrev.PrevDate=tblDatPos.colDate) AND (TabPrev.colDepNb=tblDatPos.colDepNb)
INNER JOIN dbPam.dbo.tblDefDep ON tblDefDep.colDepNb=tblDatPos.colDepNb
INNER JOIN dbPam.dbo.tblDefPortfolio ON tblDefPortfolio.colPortfolioNb = tblDefDep.colPortfolioNb
INNER JOIN dbPam.dbo.tblDefBankRel ON tblDefBankRel.colBankRelNb=tblDefPortfolio.colBankRelNb
INNER JOIN dbProd.dbo.tblDefOther ON tblDefOther.colId = tblDatPos.colId
INNER JOIN dbMktData.dbo.tblDatFX as prevFX ON (prevFX.colCcy1 = tblDefOther.colCcy ) AND (prevFX.colCcy2 = @ccy) AND (TabPrev.PrevDate=prevFX.colDate)
INNER JOIN dbMktData.dbo.tblDatFX as currFX ON (currFX.colCcy1 = tblDefOther.colCcy ) AND (currFX.colCcy2 = @ccy) AND (TabPrev.colDate=currFX.colDate)
WHERE dbPam.dbo.tblDatPos.colType = 'TRAD' and prevFX.colType = 'Bbg' and currFX.colType = 'Bbg' and tblDefPortfolio.colPortfolioNb = @portfolio
GROUP BY tblDefBankRel.colCodeClient, tblDefBankRel.colBankRelNb ,tblDefBankRel.colCcy , tblDefPortfolio.colPortfolioNb,tblDefPortfolio.colCcy , TabPrev.colDepNb, tblDefDep.colCcy , TabPrev.colId, tblDefOther.colName, tblDefOther.colCcy ) as subQuery
INNER JOIN dbPam.dbo.tblDatPos ON tblDatPos.colId = subQuery.colId AND tblDatPos.colDate = subQuery.endDate AND tblDatPos.colDepNb = subQuery.colDepNb
INNER JOIN dbPam.dbo.tblDatPos AS posPrev ON posPrev.colId = subQuery.colId AND posPrev.colDate = subQuery.startDate AND posPrev.colDepNb = subQuery.colDepNb
WHERE tblDatPos.colType = 'TRAD' and posPrev.colType = 'TRAD'
UNION all
SELECT subQuery.colCodeClient, @ccy as perfCcy, subQuery.colBankRelNb, subQuery.bankRelCcy, subQuery.colPortfolioNb, subQuery. portCcy, subQuery.colAccNb,
subQuery.accCcy, subQuery.accCcy, subQuery.accCcy,'', '','Cash', subQuery.accCcy , startDate, endDate, tblDatCash.colAmount as [finalLots], '1' ,'1', PnL
FROM
(
SELECT tblDefBankRel.colCodeClient, tblDefBankRel.colBankRelNb ,tblDefBankRel.colCcy as bankRelCcy, tblDefPortfolio.colPortfolioNb,tblDefPortfolio.colCcy as portCcy,
TabPrev.colAccNb, tblDefAccount.colCcy as accCcy, min(TabPrev.PrevDate) as startDate, max(TabPrev.colDate) as endDate,
sum(TabPrev.colAmount*(currFX.colValue-prevFX.colValue)) AS [PnL]
FROM
(SELECT dbPam.dbo.tblDatCash.colAccNb, dbPam.dbo.tblDatCash.colDate, Max(Tab_1.colDate) AS PrevDate, dbPam.dbo.tblDatCash.colAmount
FROM dbPam.dbo.tblDatCash
INNER JOIN dbPam.dbo.tblDatCash AS Tab_1 ON (dbPam.dbo.tblDatCash.colAccNb = Tab_1.colAccNb) AND (dbPam.dbo.tblDatCash.colDate > Tab_1.colDate)
WHERE dbPam.dbo.tblDatCash.colDate BETWEEN @startDate AND @endDate
GROUP BY dbPam.dbo.tblDatCash.colAccNb, dbPam.dbo.tblDatCash.colDate, dbPam.dbo.tblDatCash.colAmount ) AS TabPrev
INNER JOIN dbPam.dbo.tblDefAccount ON tblDefAccount.colAccNb = TabPrev.colAccNb
INNER JOIN dbPam.dbo.tblDefPortfolio ON tblDefPortfolio.colPortfolioNb = tblDefAccount.colPortfolioNb
INNER JOIN dbPam.dbo.tblDefBankRel ON tblDefBankRel.colBankRelNb=tblDefPortfolio.colBankRelNb
INNER JOIN dbMktData.dbo.tblDatFX as prevFX ON (prevFX.colCcy1 = tblDefAccount.colCcy ) AND (prevFX.colCcy2 = @ccy) AND (TabPrev.PrevDate=prevFX.colDate)
INNER JOIN dbMktData.dbo.tblDatFX as currFX ON (currFX.colCcy1 = tblDefAccount.colCcy ) AND (currFX.colCcy2 = @ccy) AND (TabPrev.colDate=currFX.colDate)
WHERE tblDefPortfolio.colPortfolioNb = @portfolio and prevFX.colType = 'Bbg' and currFX.colType = 'Bbg'
GROUP BY tblDefBankRel.colCodeClient, tblDefBankRel.colBankRelNb ,tblDefBankRel.colCcy , tblDefPortfolio.colPortfolioNb,tblDefPortfolio.colCcy ,
TabPrev.colAccNb, tblDefAccount.colCcy ) as subQuery
INNER JOIN dbPam.dbo.tblDatCash ON tblDatCash.colAccNb = subQuery.colAccNb AND tblDatCash.colDate = subQuery.endDate
END
期待阅读您的建议。