在VBA中执行存储过程的两种方法,哪一个更好?

时间:2014-06-20 13:40:13

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

后台:在前端Ms-Access 2010和后端SQL Server 2008 Managment Studio上工作

为了执行存储过程,我一直在使用一个非常漫长的过程,如下所示: in VBA

    Set Conn = New ADODB.connection
    Conn.ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;....."
    Conn.Open

    Set cmd = New ADODB.Command
    cmd.ActiveConnection = Conn
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "upGetTestIdForAnalyte"

    cmd.Parameters.Append cmd.CreateParameter("@WOID", adVarChar, adParamInput, 60, MySampleName)
    cmd.Parameters.Append cmd.CreateParameter("@Analyte", adVarChar, adParamInput, 60, MyAnalyte)
    cmd.Parameters.Append cmd.CreateParameter("@SampleID", adVarChar, adParamInput, 60, MyConcentration

    cmd.Execute
    Conn.Close

有人告诉我有更好的方法来执行存储过程,正确的方法是这样的: in VBA

strsql = "Exec upGetTestIdForAnalyte(WOID, Analyte, SampleID)"
test = ExecuteNonQuery(strsql)

但是我在这个过程中遇到了很多错误,我查了一下ExecuteNonQuery,它说它只适用于VB(http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx)。这个过程的一个优点是它的简洁性以及它自动连接到当前数据库的事实。我必须更改当前sp进程中的连接字符串,因为它设置为链接到测试数据库而不是实际数据库。另一个优点是它在执行时返回一个值。我想我当前的过程是这样做的,因为我想以某种方式验证它运行和我需要做的其他存储过程,需要返回受影响的记录数。

我的问题是:第二种方法是合法进程,是正确的语法吗?每个过程完成的内容是否有任何区别?还有一种方法可以让第一个进程在执行时返回一个值吗?谢谢你的时间。

更新:这是我目前正在处理的存储过程。我的sp看到是否存在testID,我会在调用sp之后继续执行该程序如果变量ThisTestId> 0否则我将引发错误testid not found

CREATE PROCEDURE upGetTestIDForAnalyte @WOID nvarchar(60), @SampleID nvarchar(60),@Analyte nvarchar(60), @Test var(20) output
AS

  SELECT TestID = t1.TestID
  FROM tblWOSampleTest t1
  JOIN tblTest t2
  ON t1.TestID=t2.TestID; 
  WHERE @WOID = t1.WOID AND @SampleID = t1.SampleID AND @Analyte = t2.Analyte

GO

3 个答案:

答案 0 :(得分:3)

此处发布的示例代码太多了。

最初的问题是海报已经看到一些例子,其中只需要一行或两行代码。

实际上,此代码可以工作并将参数传递给存储过程。

With CurrentDb.QueryDefs("MyPass")
  .SQL = "exec MySproc" & ProducutID
  .Execute
End If

以上只有两行代码。

这种方法的优点是什么?

注意我们不必弄乱(或传递)连接字符串。

注意我们不必在代码中声明任何连接对象。

请注意我们不必在代码中的任何位置存储或拥有用户名或密码。

请注意我们不必在代码中创建查询def对象。

事实上,整个过程都没有声明任何变量。

以上内容可能是用两行代码编写的,但我决定发布大量的4行代码以提高可读性。

这种设置的优点很多,但主要原因是这种方法简单易行,易于维护。

此处发布的其他解决方案仅用于强制人们编写多行代码 - 这只会增加雇主的开发成本。

答案 1 :(得分:1)

我将继续使用第一个进程并添加如下输出参数:

ccmd.parameters.Append ccmd.CreateParameter("OutParam", adInteger, adParamOuput, , NULL)   ' output parameter

您需要在存储过程中添加此参数,如下所示:

@OutParam int OUTPUT

编辑添加了OUT参数,在VBA代码中更改为整数。了解@@ROWCOUNT的工作方式

CREATE PROCEDURE upGetTestIDForAnalyte @WOID nvarchar(60), @SampleID nvarchar(60),@Analyte nvarchar(60), @RecordsAfected int OUT
AS

SELECT TestID = t1.TestID
FROM tblWOSampleTest t1
JOIN tblTest t2
ON t1.TestID=t2.TestID; 
WHERE @WOID = t1.WOID AND @SampleID = t1.SampleID AND @Analyte = t2.Analyte
set @recordsAfected = @@ROWCOUNT
GO

答案 2 :(得分:0)

来自Microsoft help site

   Function ExecuteSPT (sqltext As String, connectstring As String)

   ' Purpose: Run a temporary pass-through query.
   ' Accepts: sqltext: SQL string to run.
   '          connectstring: Connection string, which must be at least
   '          "ODBC;".
   ' Returns: nothing.

   Dim mydb As Database, myq As QueryDef
   Set mydb = DBEngine.Workspaces(0).Databases(0)

   ' Create a temporary QueryDef object that is not saved.
   Set myq = mydb.CreateQueryDef("")

   ' Set the ReturnsRecords property to False in order to use the
   ' Execute method.
   myq.returnsrecords = False

   myq.connect = connectstring
   myq.sql = sqltext

   myq.Execute
   myq.Close

   End Function

可以很容易地将其更改为DAO.Recordset。 DAO仍然是"本地人" MS Access中的数据访问。