Я действительно не понимаю, что здесь произошло. Я использую Excel VBA для подключения к базе данных SQL Server Express и возвращаю ADO Recordset. Сначала я работал, но мой код был немного беспорядочным, поэтому я создал новый модуль и скопировал код, убрав его, когда я пошел.ADO Recordset не остается открытым в VBA - «Операция не допускается, когда объект закрыт»
Теперь, когда я пытаюсь запустить Sub, чтобы вернуть учетную запись, я получаю сообщение об ошибке «Операция не допускается, когда объект закрыт». Код разбивается на строку MsgBox.
Вот упрощенный код:
Dim Server As String
Server = "ServerName"
Dim Database As String
Database = "DatabaseName"
Dim UserID As String
UserID = "UserID"
Dim Pwd As String
Pwd = "Password"
Dim StoredProcedure As String
StoredProcedure = "StoredProcedureName"
Dim conn As New ADODB.Connection
conn.ConnectionString = "Driver={SQL Server};Server=" & Server & "; Database=" & Database & "; UID = " & UserID & "; PWD=" & Pwd & ""
conn.Open
Dim Cmd As New ADODB.Command
Cmd.ActiveConnection = conn
Cmd.CommandText = StoredProcedure
Cmd.CommandType = adCmdStoredProc
Dim params() As String
ReDim Preserve params(4, 2)
params(0, 0) = "Param1"
params(1, 0) = CStr(adInteger)
params(2, 0) = CStr(adParamInput)
params(4, 0) = CStr(6)
params(0, 1) = "Param2"
params(1, 1) = CStr(adInteger)
params(2, 1) = CStr(adParamInput)
params(4, 1) = CStr(6)
params(0, 2) = "Param3"
params(1, 2) = CStr(adInteger)
params(2, 2) = CStr(adParamInput)
params(4, 2) = CStr(15)
Dim sParam4 as String
If Not sParam4 = "" Then
ReDim Preserve params(4, UBound(params, 2) + 1)
params(0, UBound(params, 2)) = "Param4"
params(1, UBound(params, 2)) = CStr(adChar)
params(2, UBound(params, 2)) = CStr(adParamInput)
params(3, UBound(params, 2)) = "1"
params(4, UBound(params, 2)) = sParam4
End If
Dim sParam5 as String
If Not sParam5 = "" Then
ReDim Preserve params(4, UBound(params, 2) + 1)
params(0, UBound(params, 2)) = "Param5"
params(1, UBound(params, 2)) = CStr(adChar)
params(2, UBound(params, 2)) = CStr(adParamInput)
params(3, UBound(params, 2)) = Len(sParam5)
params(4, UBound(params, 2)) = sParam5
End If
Dim Prm As ADODB.Parameter
Set Prm = New ADODB.Parameter
Dim i As Integer
For i = 0 To UBound(params, 2)
If params(1, i) = CStr(adChar) Then
Set Prm = Cmd.CreateParameter(params(0, i), CInt(params(1, i)), CInt(params(2, i)), CInt(params(3, i)))
Cmd.Parameters.Append Prm
Cmd.Parameters(params(0, i)).Value = params(4, i)
Else
Set Prm = Cmd.CreateParameter(params(0, i), CInt(params(1, i)), CInt(params(2, i)))
Cmd.Parameters.Append Prm
Cmd.Parameters(params(0, i)).Value = CInt(params(4, i))
End If
Next i
Dim rs As New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.Open Cmd, , adOpenStatic, adLockOptimistic
MsgBox ("Success! " & rs.RecordCount & " Records Returned!")
Когда я смотрю на переменную Rs в окне Locals, все свойства перечислены как показывает то же самое сообщение об ошибке. Для меня кажется, что набор записей открывается правильно, но затем сразу же закрывается.
Что странно в том, что оригинальная (грязная) подставка теперь также не работает, бросая ту же ошибку. Я не думаю, что я что-то там что-то изменил, просто скопировал его на новый.
Я прокомментировал весь модуль, в котором находился старый юзер, на всякий случай, когда происходит какая-то конфликтная переменная. Это не имело никакого значения.
Я просто не вижу, что с этим не так! Я много исследовал и читал, и к моему неподготовленному, но восторженному глазу, все кажется прекрасным.
Любая помощь будет высоко оценена.
EDIT: Вот хранимая процедура:
USE [MyDatabase]
GO
/****** Object: StoredProcedure [dbo].[MyProcedure] Script Date: 14/09/2015 11:39:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[MyProcedure]
-- Add the parameters for the stored procedure here
@Param1 int, @Param2 int, @Param3 int, @Param4 char(1), @Param5 varchar(20) = NULL, @Param6 varchar(20) = NULL, @Param7 varchar(20) = NULL
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET ANSI_WARNINGS OFF;
-- Insert statements for procedure here
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SET @cols = '';
SELECT @cols = @cols + ',' + QUOTENAME([Field3]) FROM View1
WHERE Field2 = @Param2 AND Field1 = @Param1
SET @cols = STUFF(@cols,1,1,'');
IF @Param5 IS NOT NULL
SET @query = 'SELECT Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11, Field12, Field13, Field14,' + @cols + ' FROM
(
SELECT
Table1.Field1,
Table1.Field2,
Table1.Field3,
Table1.Field4,
Table1.Field5,
Table1.Field6,
Table1.Field7,
Table1.Field8,
Table1.Field9,
Table1.Field10,
Table1.Field11,
Table1.Field12,
Table1.Field13,
Table1.Field14,
Table2.Field2,
Table3.Field1
FROM Table3
LEFT OUTER JOIN Table2 ON Table3.Field1 = Table2.Field1
AND Table3.Field2 = Table2.Field2
LEFT OUTER JOIN Table4 ON Table3.Field4 = Table4.Field1
AND Table3.Field2 = Table4.Field3
RIGHT OUTER JOIN Table1 ON Table2.Field1 = Table1.Field1
AND Table2.Field2 = Table1.Field15
WHERE Table1.Field2 = ' + CAST(@Param3 AS char(1)) + '
AND Table1.Field12 = ''' + @Param5 + '''
AND Table1.Field15 = ' + CAST(@Param1 AS char(2)) + '
)
AS UP
PIVOT(MAX(Field2) FOR UP.ID IN (' + @cols + ')) AS PVT '
ELSE IF @Param6 IS NOT NULL
SET @query = 'SELECT Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11, Field12, Field13, Field14,' + @cols + ' FROM
(
SELECT
Table1.Field1,
Table1.Field2,
Table1.Field3,
Table1.Field4,
Table1.Field5,
Table1.Field6,
Table1.Field7,
Table1.Field8,
Table1.Field9,
Table1.Field10,
Table1.Field11,
Table1.Field12,
Table1.Field13,
Table1.Field14,
Table2.Field2,
Table3.Field1
FROM Table3
LEFT OUTER JOIN Table2 ON Table3.Field1 = Table2.Field1
AND Table3.Field2 = Table2.Field2
LEFT OUTER JOIN Table4 ON Table3.Field4 = Table4.Field1
AND Table3.Field2 = Table4.Field3
RIGHT OUTER JOIN Table1 ON Table2.Field1 = Table1.Field1
AND Table2.Field2 = Table1.Field15
WHERE Table1.Field2 = ' + CAST(@Param3 AS char(1)) + '
AND Table1.Field13 = ''' + @Param6 + '''
AND Table1.Field15 = ' + CAST(@Param1 AS char(2)) + '
)
AS UP
PIVOT(MAX(Field2) FOR UP.ID IN (' + @cols + ')) AS PVT '
ELSE IF @Param7 IS NOT NULL
SET @query = 'SELECT Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11, Field12, Field13, Field14,' + @cols + ' FROM
(
SELECT
Table1.Field1,
Table1.Field2,
Table1.Field3,
Table1.Field4,
Table1.Field5,
Table1.Field6,
Table1.Field7,
Table1.Field8,
Table1.Field9,
Table1.Field10,
Table1.Field11,
Table1.Field12,
Table1.Field13,
Table1.Field14,
Table2.Field2,
Table3.Field1
FROM Table3
LEFT OUTER JOIN Table2 ON Table3.Field1 = Table2.Field1
AND Table3.Field2 = Table2.Field2
LEFT OUTER JOIN Table4 ON Table3.Field4 = Table4.Field1
AND Table3.Field2 = Table4.Field3
RIGHT OUTER JOIN Table1 ON Table2.Field1 = Table1.Field1
AND Table2.Field2 = Table1.Field15
WHERE Table1.Field2 = ' + CAST(@Param3 AS char(1)) + '
AND Table1.Field14 = ''' + @Param7 + '''
AND Table1.Field15 = ' + CAST(@Param1 AS char(2)) + '
) AS UP
PIVOT(MAX(Field2) FOR UP.ID IN (' + @cols + ')) AS PVT '
ELSE
SET @query = 'SELECT Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11, Field12, Field13, Field14,' + @cols + ' FROM
(
SELECT
Table1.Field1,
Table1.Field2,
Table1.Field3,
Table1.Field4,
Table1.Field5,
Table1.Field6,
Table1.Field7,
Table1.Field8,
Table1.Field9,
Table1.Field10,
Table1.Field11,
Table1.Field12,
Table1.Field13,
Table1.Field14,
Table2.Field2,
Table3.Field1
FROM Table3
LEFT OUTER JOIN Table2 ON Table3.Field1 = Table2.Field1
AND Table3.Field2 = Table2.Field2
LEFT OUTER JOIN Table4 ON Table3.Field4 = Table4.Field1
AND Table3.Field2 = Table4.Field3
RIGHT OUTER JOIN Table1 ON Table2.Field1 = Table1.Field1
AND Table2.Field2 = Table1.Field15
WHERE Table1.Field2 = ' + CAST(@Param3 AS char(1)) + '
AND Table1.Field3 = ''' + @Param4 + '''
AND Table1.Field15 = ' + CAST(@Param1 AS char(2)) + '
) AS UP
PIVOT(MAX(Field2) FOR UP.ID IN (' + @cols + ')) AS PVT '
EXECUTE (@query)
Set NOCOUNT OFF;
END
Я знаю, что логика параметров не очень ... логично .. но это работает так, как мне нужно это сейчас. Это то, что я изменил, когда я работаю над этим.
Я также должен сказать, что я пропустил раздел моего кода VBA, который обрабатывает параметры для SP, когда я впервые разместил вопрос. Сейчас я просто ухожу, но я добавлю его, когда вернусь домой. Я не думаю, что проблема там. Я в основном работаю через строковый массив параметров и добавляю их к объекту Cmd
.
EDIT: Я добавил код для создания параметров и передачи их объекту Cmd
. Опять же, это немного запутанно, но это то, что вышло из моей головы в то время, и оно действительно работает. Я вернусь к логике после заполнения набора записей.
Предлагаю вам научиться никогда не использовать 'Dim ... As New'. Используйте две строки: 'Dim rs As ADODB.Recordset', затем' Set rs = New ADODB.Recordset'. Затем попробуйте выполнить код по строкам. – Rory
@Rory Ah man, я изначально отделил выражения 'Dim' и' Set', но, исследуя, что может быть неправильно, я изменил их все! Я поменяю их прямо назад. Просто из интереса, в чем причина того, чтобы делать это правильно? –
Я бы также предложил, чтобы вы посмотрели свою хранимую процедуру. Если он не возвращает записи, вы получите закрытый набор записей. Это также может произойти, если сначала выполняется какая-то другая обработка, и вы не использовали 'SET NOCOUNT ON' – Rory