Sql server 将表记录集传递给SQL server

Sql server 将表记录集传递给SQL server,sql-server,tsql,ms-access,pass-through,Sql Server,Tsql,Ms Access,Pass Through,各位专家下午好 我遇到了一种与平常截然不同的问题。过去,我通过“直通查询”将一行数据传递给服务器,有时需要传递多条记录时,我会使用循环功能将数据多次发送到服务器。然而,如果我有超过40行的记录,那么循环将需要相当长的时间才能完成。我只是想知道是否有一种方法可以在1次移动中将表集发送到服务器,而不是使用循环发送X次移动 这是我在访问端使用的代码,附加到表单中的按钮上(recordsource是本地访问表): 现在,在SQL server端,我有以下存储过程(dbo.SP_Client_refere

各位专家下午好

我遇到了一种与平常截然不同的问题。过去,我通过“直通查询”将一行数据传递给服务器,有时需要传递多条记录时,我会使用循环功能将数据多次发送到服务器。然而,如果我有超过40行的记录,那么循环将需要相当长的时间才能完成。我只是想知道是否有一种方法可以在1次移动中将表集发送到服务器,而不是使用循环发送X次移动

这是我在访问端使用的代码,附加到表单中的按钮上(recordsource是本地访问表):

现在,在SQL server端,我有以下存储过程(dbo.SP_Client_reference),它从直通查询接收数据,并将代码行插入到特定的表中

    @ClientID AS NVARCHAR(15),
    @Note As NVARCHAR(500),
    @Value1 As NVARCHAR(50),
    @Value2 As NVARCHAR(50)
AS  

BEGIN

    SET NOCOUNT ON;

        BEGIN
        INSERT INTO dbo.Client_Data(ClientID, Note, Value_1, Value_2)
        SELECT @ClientID, @Note, @Value1, @Value2
        END

END
对于单个记录,甚至多达10条记录,这种方法相对较快。然而,随着记录数量的增加,所需的时间可能会相当长。如果有一种方法将表(即使用SELECT*from LocalTable)传递到SQL server,而不是逐行传递,那么肯定会节省大量时间。只是想知道这个方法是否存在,如果存在,我将如何发送一个表,以及我必须在SP的SQL server端使用什么来接收表记录。或者,我可能不得不继续使用这一单行方法,并可能使其更有效,以使其执行更快


非常感谢您的帮助

您可以尝试将XML数据传递到存储过程

DECLARE @rowData XML

SELECT @rowData = '<data><record clientid="01" Notes="somenotes" Value1="val1" Value2="val2" /><record clientid="02" Notes="somenotes 2" Value1="val1-2" Value2="val2-2" /></data>'

SELECT X.custom.value('@clientid', 'varchar(max)'),
    X.custom.value('@Notes', 'varchar(max)'),
    X.custom.value('@Value1', 'varchar(max)'),
    X.custom.value('@Value2', 'varchar(max)')
FROM @rowData.nodes('/data/record') X(custom)
DECLARE@rowdataxml
选择@rowData=''
选择X.custom.value(“@clientid”,“varchar(max)”,
X.custom.value(“@Notes”,“varchar(max)”),
X.custom.value(“@Value1”,“varchar(max)”),
X.custom.value('@Value2','varchar(max)'
来自@rowData.nodes('/data/record')X(自定义)

实际上,最快的方法是什么

嗯,这似乎是一个非常违反直觉的问题,我可以给出一个很长的解释,为什么。然而,试试这个,你会发现它比你现在拥有的运行了10倍甚至更好。事实上,它很可能比你所拥有的更接近100倍

我们假设我们有一个标准的链接到
dbo.Client\u数据的链接。很可能链接是
Client\u Data
,甚至是
dbo\u Cliet\u Data

因此,请使用以下命令:

Dim rs      As DAO.Recordset
Dim rsIns   As DAO.Recordset

If Me.Dirty = True Then Me.Dirty = False  ' write any pending data

Set rsIns = CurrentDb.OpenRecordset("dbo_Client_Data", dbOpenDynaset, dbSeeChanges)

Set rs = Me.RecordsetClone
rs.MoveFirst

Do While Not rs.EOF
   With rsIns
      .AddNew
      !ClientID = rs!ClientID
      !Note = Me.Txt_Note
      !Value_1 = Me.Txt_Value1
      !Value_2 = Me.Txt_Value2
      .Update
   End With

   rs.MoveNext
Loop
rsIns.Close
MsgBox "All Client Added!", , "Add client"
请注意上面的一些奖金。我们的代码是干净的-我们不必担心诸如日期之类的数据类型,也不必担心您混乱的报价问题。如果涉及日期,我们也可以直接分配,而不必担心分隔符。我们还获得了开机时的注射保护奖励

我们还使用了
me.RecordSetClone
。这不是必须做的。这将有助于提高性能,但最重要的是,当您移动记录指针时,表单记录位置不会尝试跟随。这将消除许多潜在的闪烁。如果表单上存在当前事件,它还可以消除重大问题

因此,尽管这是一个非常好的主意(recordsetclone),但它并不是您将在这里看到的性能大幅提高的主要原因
RecordSetClone
me.RecordSet
相同,但您可以“移动”并遍历记录集,而无需以下主要形式

因此,事实证明,最“基本”的代码方法,也就是说,在没有SQL Server的情况下使用access是最好的方法。它减少了代码,减少了混乱的代码,并且将为您省去安装并构建SQL Server存储过程的所有麻烦。您的所有概念都不是必需的,更糟糕的是,它们将导致性能损失。试试上面的概念

Access将一次放大并管理多个插入。与REOCRDSET相比,始终使用SQL更新/插入命令的概念和想法是一个非常巨大的城市神话,许多access开发人员都为之着迷。这不是真的。真正的问题是,如果您可以用一条SQL update语句替换大量(比如说单独执行的)更新的VBA循环,那么是的,您领先了几英里(在某个VBA循环上使用一个SQL更新)


但是,如果您必须执行多个操作,并且每个操作都在一行上?代替“许多单独的”SQL更新,那么在本例中,(作为)绝大多数情况下,记录集将围绕一系列单独的更新/插入命令运行循环,以实现相同的目标。它甚至还不接近,通过使用上述概念,您可以获得10倍甚至100倍的性能

请学习参数化。该语句中存在一些巨大的注入问题。您可以使用VBA代码创建JSON(SQL Server 2016+)或XML(较低版本),并将其作为单个参数传递。然后,您可以使用SQL Server处理JSON/XML的能力一次插入所有内容。该SP是实际的代码,还是实际的SP对数据进行了更多的处理?看到如此多的代码用于这样一个基本任务(将记录从本地插入到服务器表),我感到很痛苦。有什么理由不在Access中使用链接表吗?感谢您的评论,我没有使用链接表,因为如果我可以帮助的话,我不希望用户在Access级别与实际的SQL表交互。我希望通过SP与表进行交互,以减少可能出错的问题数量。因此,SP和pass-through查询。我将查看JSON/XML选项,看看这是否可行:)谢谢您的提示
Dim rs      As DAO.Recordset
Dim rsIns   As DAO.Recordset

If Me.Dirty = True Then Me.Dirty = False  ' write any pending data

Set rsIns = CurrentDb.OpenRecordset("dbo_Client_Data", dbOpenDynaset, dbSeeChanges)

Set rs = Me.RecordsetClone
rs.MoveFirst

Do While Not rs.EOF
   With rsIns
      .AddNew
      !ClientID = rs!ClientID
      !Note = Me.Txt_Note
      !Value_1 = Me.Txt_Value1
      !Value_2 = Me.Txt_Value2
      .Update
   End With

   rs.MoveNext
Loop
rsIns.Close
MsgBox "All Client Added!", , "Add client"