从VBA

时间:2018-04-13 22:34:50

标签: sql sql-server vba

我正在使用VBA从SQL Server中提取信息。为了不复杂,请阅读:

“我在SQL中有一个存储过程,它接收一个日期(@NeededDate作为日期)&逗号分隔文本(@DelimitedAssets作为NVARCHAR(MAX)返回所需的结果。

当我在VBA中运行我的代码时,当我传递的文本(@DelimitedAssets)不超过7000个字符(这不是确切的数字但是接近)时,它工作。所以,改写一下:如果字符串不大,代码将按预期工作。

但是我从VBA传递给存储过程的文本总计最多12000个字符。 NVARCHAR应该能够处理它,但是当我从VBA传递它时它没有这样做。

重要提示:如果我从SQL Server Management Studio运行相同的数据块(12000个字符),它将完美运行。没有错误,数据还可以。

VBA Error

线上的错误:

Set oRecordSet = .Execute

VBA代码*

Private Function RunMonthlyPricesSP(ByVal strDate As String, ByRef strAssetsDelimted As String, ByRef cnAccounting As Object, ByRef rDestination As Range) As Variant

    Dim oCmd As ADODB.Command
    Dim oRecordSet As ADODB.Recordset
    Dim ActivityParam As ADODB.Parameter
    Dim varPrices As Variant
    Dim strAction As String

    Set oCmd = New ADODB.Command
    Set oRecordSet = New ADODB.Recordset

    With oCmd
        .ActiveConnection = cnAccounting
        .CommandType = adCmdStoredProc
        .CommandText = "Usp_bondselectionprices"

        .Parameters("@NeededDate").Value = strDate
        .Parameters("@DelimitedAssets").Value = strAssetsDelimted

        Set oRecordSet = .Execute
    End With


    ' Return Array.
    ' Pending.
End Function

SQL STORED PROCEDURE *

GO
/****** Object:  StoredProcedure [dbo].[Usp_bondselectionprices]    Script Date: 4/13/2018 5:41:57 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[Usp_bondselectionprices] @NeededDate      DATE,
                                                @DelimitedAssets VARCHAR(max)
AS
  BEGIN
      DECLARE @TblBuysSelectionBond BUYSSELECTIONBONDS

      INSERT INTO @TblBuysSelectionBond
      SELECT *
      FROM   dbo.Splittext(@DelimitedAssets)

      SELECT CASE
               WHEN Prices.Price * CurrencyPrices.Price IS NULL THEN Prices.Price
               ELSE Prices.Price * CurrencyPrices.Price
             END AS Price,
             Assets.AssetName
      FROM   Prices
             INNER JOIN Assets
                     ON Prices.AssetID = Assets.AssetID
             INNER JOIN Assets AS Currencies
                     ON Assets.CurrencyID = Currencies.AssetID
             LEFT OUTER JOIN Prices AS CurrencyPrices
                          ON Currencies.AssetID = CurrencyPrices.AssetID
                             AND Prices.PriceDate = CurrencyPrices.PriceDate
      WHERE  prices.PriceDate = @NeededDate
             AND assets.InstrumentTypeID = 4
             AND Assets.AssetName IN (SELECT *
                                      FROM   @TblBuysSelectionBond)
  END 

从存储过程中调用的功能将文本转换为表格*

GO
/****** Object:  UserDefinedFunction [dbo].[Splittext]    Script Date: 4/13/2018 6:10:02 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER FUNCTION [dbo].[Splittext] (@input AS VARCHAR(max))
RETURNS @Result TABLE(
  Value VARCHAR(max))
AS
  BEGIN
      DECLARE @str VARCHAR(max)
      DECLARE @ind bigint

      IF( @input IS NOT NULL )
        BEGIN
            SET @ind = Charindex(',', @input)

            WHILE @ind > 0
              BEGIN
                  SET @str = Substring(@input, 1, @ind - 1)
                  SET @input = Substring(@input, @ind + 1, Len(@input) - @ind)

                  INSERT INTO @Result
                  VALUES      (@str)

                  SET @ind = Charindex(',', @input)
              END

            SET @str = @input

            INSERT INTO @Result
            VALUES      (@str)
        END

      RETURN
  END 

请记住,这适用于小字符串分隔文本。所以我们知道我的连接和其他参数都没问题。

谢谢,

2 个答案:

答案 0 :(得分:1)

确定。我找到了解决方案,非常非常容易。这就是为什么检查Watch窗口以了解你的对象(在这种情况下是oCMD)内部的重要性。

默认情况下,它将参数@DelimitedAssets作为adVarChar。您需要指定它不是adVarChar而是adLongVarChar。

.Parameters("@DelimitedAssets").Value = strAssetsDelimted
.Parameters("@DelimitedAssets").Type = adLongVarChar

一旦我改变了这一切,一切都按预期工作。

希望这有帮助。

答案 1 :(得分:0)

您是否尝试过指定类型&尺寸?

param.SqlDbType = SqlDbType.VarChar;
param.Size = -1;