将用户定义的表类型从 VBA 传递到 SQL

Posted

技术标签:

【中文标题】将用户定义的表类型从 VBA 传递到 SQL【英文标题】:Pass user-defined table type from VBA to SQL 【发布时间】:2013-06-07 03:35:55 【问题描述】:

我的任务是创建一个 Excel 电子表格作为 SQL 数据库的前端和一些对数据执行复杂计算的 C#。我的老板希望前端是一个电子表格,而 VBA 的计算似乎太复杂了。

目前,检索数据集的存储过程工作正常。然后,用户将在 Excel 中编辑数据并将其发送回数据库。数据需要作为一个新集合插入,保留之前集合的记录。因此,我编写了以下 SQL 存储过程来完成这项任务:

DECLARE @Now DATETIME = GETDATE()
DECLARE @DataSetID SMALLINT = (SELECT ISNULL(MAX([DataSetID]), 0) FROM [dbo].[tbl_DataSet]) + 1

--Add DataSet entry
INSERT INTO [dbo].[tbl_DataSet] ([DataSetID], [InputDate])
SELECT @DataSetID, @Now

--Add latest data
INSERT INTO [dbo].[tbl_Data] ([DataSetID], [DataID], [Amount])
SELECT @DataSetID, [DataID], [Amount]
FROM @DataTable
ORDER BY [DataID]

这意味着 VBA 代码需要能够调用存储过程,传入用户定义的表类型参数 @DataTable AS [dbo].[typ_DataTable] READONLY。

我目前调用 SQL 用户存储过程的方法,传入标准数据类型参数:

Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.ConnectionString = getConnectionString()
cnn.CursorLocation = adUseClient
cnn.Open

Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.Parameters.Append cmd.CreateParameter("in", adInteger, adParamInput, , 1)
cmd.Parameters.Append cmd.CreateParameter("bReturn", adBoolean, adParamOutput)
cmd.ActiveConnection = cnn
cmd.CommandText = ProcedureName
cmd.CommandType = adCmdStoredProc

Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
Set rst = cmd.Execute()

有没有简单的方法传入用户定义的表类型?

或者,我可以使用一个更好的系统来执行此操作吗?

目前我能想到的唯一解决方法是将数据传递给 C#,然后使用以下命令发送到数据库:

command.Parameters.Add(new SqlParameter 
    ParameterName = "@DataTable",
    Value = dataTable,
    TypeName = "[dbo].[typ_DataTable]",
    SqlDbType = SqlDbType.Structured ); 

不过,这似乎有点迂回。

谢谢。

更新:

由于已经存在从 C# 到 Excel 的管道,因此最好利用这一讨厌的代码,而不是在 Excel SQL 中引入第二个代码。 C# 也可以很容易地用于转换数据类型并验证任何参数或返回变量。使用 VBA 到 C# 的伪异步方法也将改进 Excel 界面,防止在 UI 线程上挂起。

【问题讨论】:

回复:“有没有更好的系统可以用来做这个” - 是的,任何设计为前端的东西,电子表格不是。如果您可以使用 .NET 框架,则填充 Gridview(在 Windows 或 Web 应用程序中)、编辑并将编辑发送回数据库不会很复杂。 不幸的是,需要 Excel 电子表格。那句话是关于数据库布局和数据集插入方法的。 @user1765603,我正在尝试做与您类似的事情。你是说你可以用你的第二个代码块来完成传递一个表值参数? Elias,该代码适用于标准数据类型,但我无法让它适用于表类型。我的第一个解决方案是使用预先存在的 C# 项目作为数据库和 Excel 前端之间的接口,效果很好。现在,我随后创建了自己的前端,因为 Excel/VBA 不利于这类项目。 【参考方案1】:

ADO 有一个非常好的表格类型。

“目前,检索数据集的存储过程工作正常。”

分离数据集。

然后用户将在 Excel 中编辑数据...

将新数据附加到分离的数据集。从分离的数据集中删除旧数据

...并将其发送回数据库。

重新附加数据集。更新数据:

myRecordSet.ActiveConnection=oConnection
myRecordSet.UpdateBatch

【讨论】:

以上是关于将用户定义的表类型从 VBA 传递到 SQL的主要内容,如果未能解决你的问题,请参考以下文章

使用 JDBC 将用户定义的表类型传递给 SQL Server 存储过程

使用 JDBC 将用户定义的表类型传递给 SQL Server 存储过程

在 SQL Server 数据库之间传递用户定义的表类型

用户定义的表类型是否拒绝EXECUTE权限?

如何从 SQL Server 2014 中的 Select 查询中将数据分配给用户定义的表类型

SQL Server中用户定义的表类型的性能