我的Excel VBA记录集有问题,它运行所有其他查询,但是在SQL Server中运行的这一个特定查询不能使用Recordset打开。 这是代码块:
SQL2 = "DECLARE @val VARCHAR (2000) " & vbCrLf & "DECLARE @cert VARCHAR(2000) " & vbCrLf & _
"DECLARE @inv VARCHAR(2000) " & vbCrLf & "DECLARE @loc INT " & vbCrLf & _
"DECLARE @res TABLE(val VARCHAR(100)) " & vbCrLf & _
"DECLARE @Delimiter VARCHAR(2) " & vbCrLf & "SET @val = '' " & vbCrLf & _
"SET @Delimiter = ',' " & vbCrLf & "SELECT @cert = " & vbCrLf & "CASE WHEN @cert = '' " & vbCrLf & _
"THEN CertInvsRec " & vbCrLf & "ELSE @cert + coalesce(',' + CertInvsRec, '') " & vbCrLf & _
"End " & vbCrLf & "FROM ProjValuations WHERE (Proj = 'TPL-15-020') " & vbCrLf & _
"SELECT @inv = " & vbCrLf & "CASE WHEN @inv = '' " & vbCrLf & "THEN InvsAmountRec " & vbCrLf & _
"ELSE @inv + coalesce(',' + InvsAmountRec, '') " & vbCrLf & "End " & vbCrLf & _
"FROM ProjValuations WHERE (Proj = 'TPL-15-020') " & vbCrLf & "SET @val = CONCAT(@inv, ',', @cert) " & vbCrLf & _
"IF NOT @val = ',' " & vbCrLf & "DECLARE @Index SMALLINT, @Start SMALLINT, @DelSize SMALLINT " & vbCrLf & _
"SET @DelSize = LEN(@Delimiter) " & vbCrLf & "WHILE LEN(@val) > 0 " & vbCrLf & "BEGIN " & vbCrLf & _
"SET @Index = CHARINDEX(@Delimiter, @val) " & vbCrLf & "IF @Index = 0 " & vbCrLf & "BEGIN " & vbCrLf & _
"INSERT INTO @res(val) VALUES(LTRIM(RTRIM(@val))) " & vbCrLf & "BREAK " & vbCrLf & _
"End " & vbCrLf & "Else " & vbCrLf & "BEGIN " & vbCrLf & _
"INSERT INTO @res (val) VALUES (LTRIM(RTRIM(SUBSTRING(@val, 1,@Index - 1)))) " & vbCrLf & _
"SET @Start = @Index + @DelSize " & vbCrLf & _
"SET @val = SUBSTRING(@val, @Start , LEN(@val) - @Start + 1) " & vbCrLf & "End " & vbCrLf & _
"End " & vbCrLf & vbCrLf & "SELECT " & vbCrLf & "( " & vbCrLf & _
"SELECT sum(InvTotExcl) FROM invnum WHERE autoindex in ( " & vbCrLf & _
"SELECT iInvoiceID FROM _bvSalesOrdersFull WHERE (ProjectCode LIKE '%020%') AND " & vbCrLf & _
"(StatusDescription = 'CERTIFICATE') and iInvoiceID not in (SELECT * FROM @res)) " & vbCrLf & _
") " & vbCrLf & " AS certAmnt, " & vbCrLf & "( " & vbCrLf & _
"SELECT SUM(InvTotExcl) FROM _bvSalesOrdersFull WHERE (ProjectCode = 'TPL-15-020') AND " & vbCrLf & _
"(StatusDescription = 'STANDARD') and iInvoiceID not in (SELECT * FROM @res) " & vbCrLf & ") AS invAmnt"
If rsAmnts.State = adStateOpen Then rsAmnts.Close
rsAmnts.Open SQL2, CN, adOpenStatic, adLockReadOnly
任何帮助都将受到高度赞赏,提前谢谢。
如果有帮助,如果我使用直接SELECT查询,例如它运行的 SELECT * FROM ,可能是因为变量声明,所以我应该将查询移到一个过程?
答案 0 :(得分:1)
因此,我发现有效的解决方案是通过SQL查询创建一个过程
/****** Object: StoredProcedure [dbo].[valuationReports] Script Date: 1/9/2017 17:24:26 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[valuationReports]
@proj AS VARCHAR(200)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @val VARCHAR (2000)
DECLARE @cert VARCHAR(2000)
DECLARE @inv VARCHAR(2000)
DECLARE @loc INT
DECLARE @res TABLE(val VARCHAR(100))
DECLARE @Delimiter VARCHAR(2)
SET @val = ''
SET @Delimiter = ','
SELECT @cert = coalesce(',' + CertInvsRec, '')
FROM ProjValuations WHERE (Proj = @proj)
SELECT @inv = coalesce(',' + InvsAmountRec, '')
FROM ProjValuations WHERE (Proj = @proj)
SET @val = CONCAT(@inv, ',', @cert)
--select @val as 'tst'
IF NOT @val = ','
BEGIN
DECLARE @Index SMALLINT, @Start SMALLINT, @DelSize SMALLINT
SET @DelSize = LEN(@Delimiter)
WHILE LEN(@val) > 0
BEGIN
SET @Index = CHARINDEX(@Delimiter, @val)
IF @Index = 0
BEGIN
INSERT INTO @res(val) VALUES(LTRIM(RTRIM(@val)))
BREAK
END
ELSE
BEGIN
INSERT INTO @res (val) VALUES (LTRIM(RTRIM(SUBSTRING(@val, 1,@Index - 1))))
SET @Start = @Index + @DelSize
SET @val = SUBSTRING(@val, @Start , LEN(@val) - @Start + 1)
END
END
END
SET @cert = ''
SET @inv = ''
SELECT @cert =
CASE WHEN @cert = ''
THEN cast(iInvoiceID as varchar)
ELSE @cert + coalesce(',' + cast(iInvoiceID as varchar), '')
END
FROM _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND
(StatusDescription = 'CERTIFICATE') AND iInvoiceID NOT IN (SELECT * FROM @res)
SELECT @inv =
CASE WHEN @inv = ''
THEN cast(iInvoiceID as varchar)
ELSE @inv + coalesce(',' + cast(iInvoiceID as varchar), '')
END
FROM _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND
(StatusDescription = 'STANDARD') AND iInvoiceID NOT IN (SELECT * FROM @res)
SELECT
(
SELECT ISNULL(SUM(InvTotExcl), 0) FROM invnum WHERE autoindex in (
SELECT iInvoiceID FROM _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND
(StatusDescription = 'CERTIFICATE') AND iInvoiceID NOT IN (SELECT * FROM @res)
)
) AS 'cert',
(
SELECT ISNULL(SUM(InvTotExcl), 0) FROM _bvSalesOrdersFull WHERE (ProjectCode = @proj) AND
(StatusDescription = 'STANDARD') AND iInvoiceID NOT IN (SELECT * FROM @res)
) AS 'inv',
(
SELECT ISNULL(@cert, '')
) AS 'certIn',
(
SELECT ISNULL(@inv, '')
) AS 'invIn'
END
GO
我使用的VBA代码是
'Declare variables
Dim CN As Connection
Dim cmd As Command, rsAmnts As Recordset
'Initialise the variables
Set CN = New Connection
Set cmd = New Command
'Open connection
CN.Open ("connection string")
'Call procedure assigning the variable
cmd.ActiveConnection = CN
cmd.CommandText = "valuationReports"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
'The variable assigned a value
cmd(1) = "TP-15-0020"
'Set Recordset by executing the command i.e. procedure
Set rsAmnts = cmd.Execute
希望这可以帮助那里的任何人
答案 1 :(得分:0)
答案 2 :(得分:0)
这可能不是直接的答案,但它不符合评论并可能解决问题。
您正在使用Connection.Open
根据this可能无法立即为您提供记录集: -
打开与数据源的连接。
和
在客户端Connection对象上使用时,Open方法实际上并未建立与服务器的连接,直到在Connection对象上打开Recordset为止。
可能是将它分配给Recordset
对象的情况会将其公开为记录集。
而使用Connection.Execute
,根据this将返回记录集: -
返回Recordset对象(ADO)对象引用。
和
执行指定的查询,SQL语句,存储过程或特定于提供程序的文本。
我从中读到的是Connection.Open
将打开一个连接,这可能不是执行特定命令的情况,而只是打开对数据的访问。 Connection.Execute
明确提到运行查询和命令,因此可以接受您的声明以及标准查询。
执行的快速示例: -
Public Sub Sample(ByVal SQL2 As String)
Dim DBConn As ADODB.Connection
Dim RS As ADODB.Recordset
Set DBConn = New ADODB.Connection
DBConn.Open "Provider=SQLOLEDB;Server=[SERVER];Database=[DATABASE];User Id=[USER];Password=[PASSWORD;"
Set RS = DBConn.Execute(SQL2)
'RS is a recordset at this point
RS.Close
Set RS = Nothing
DBConn.Close
Set DBConn = Nothing
End Sub
答案 3 :(得分:0)
确保检查区域设置,这将影响数据输入数据库的方式