【问题标题】:How to pass a list of parameter to stored procedure and perform batch insert in SQL Server如何将参数列表传递给存储过程并在 SQL Server 中执行批量插入
【发布时间】:2014-02-21 06:33:41
【问题描述】:

我正在使用 Spring JDBCTemplate 连接到 SQL Server。

我有一个需要插入到 SQL Server 表中的对象列表。

我所做的如下:

public void batchInsert(final List<Bean> list) {

    final String sql = "insert into temp"
            + "(id, name, amount, location, time, price) "
            + " values (?, ?, ?, ?, ?, ?)";

    getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {

        @Override
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            Bean vo = list.get(i);
            ps.setString(1, vo.getId());
            ps.setString(2, vo.getName());
            ps.setDouble(3, vo.getAmount());
            ps.setString(4, vo.getLocation());
            ps.setString(5, vo.getTime());
            ps.setDouble(6, vo.getPrice());
        }

        @Override
        public int getBatchSize() {
            return list.size();
        }
    });
}

但是现在,我想将参数List&lt;Bean&gt; list 传递给一个存储过程,该过程尽可能高效地处理批量插入。

请问如何实现?

【问题讨论】:

  • 根据您的 SQL Server 版本,您可能需要查看Table valued parameters
  • 没关系,它看起来像 JDBC doesn't support them yet,虽然这将是前进的方向。 This thread 建议解决方法,但不是很清楚,而且我对 Java 的了解不够,恐怕无法提供帮助。

标签: sql sql-server spring stored-procedures jdbc


【解决方案1】:

首先,不要直接编写查询,因为它可能会破坏您的应用程序的安全性。对于大容量数据存储,通常遵循的方式是 XML 方式。尝试通过 XML 实现。

【讨论】:

    【解决方案2】:

    您可以为您的存储过程使用表变量参数:

    CREATE TYPE RecordList AS TABLE (Id Int, Name NVarChar(100), Amount int, location nvarchar(100), ...)
    
    CREATE PROCEDURE test 
        @RecordList dbo.RecordList READONLY
    AS Begin
        Insert Into temp (id, name, amount, location , ...)
        Select id, name, amount, location, ...)
        from @RecordList
    End
    

    我不使用 Spring JDBCTemplate,但您可以使用以下参考来在 C# 中使用表变量参数:

    How to pass table value parameters to stored procedure from .net code

    C# and Table Value Parameters

    【讨论】:

      【解决方案3】:

      如果不能使用表值参数,为什么不在存储过程中使用 xml 参数?

      【讨论】:

      • 请您再多一点
      【解决方案4】:

      将 XML 解析为数据集:

      DECLARE @ParseXML xml
      
      --SET @ParseXML  = ?        Your xml, don't use UTF-8
      SET  @ParseXML = '
      <row>
        <id>1</id>
        <name>Alex</name>
        <amount>3</amount>
        <location>GBR</location>
        <time>2014-02-27T08:25:19.113</time>
        <price>5.25</price>
      </row>
      <row>
        <id>2</id>
        <name>John</name>
        <amount>1</amount>
        <location>USA</location>
        <time>2014-02-27T08:25:19.113</time>
        <price>3.00</price>
      </row>
      <row>
        <id>3</id>
        <name>Sam</name>
        <amount>4</amount>
        <location>CAN</location>
        <time>2014-02-27T08:25:19.113</time>
        <price>7.55</price>
      </row>
      ';
      
      --INSERT INTO Temp
      SELECT
          T.c.value('./id[1]','int') as id
          ,T.c.value('./name[1]','nvarchar(255)') as name
          ,T.c.value('./amount[1]','int') as amount
          ,T.c.value('./location[1]','nvarchar(255)') as location
          ,T.c.value('./time[1]','datetime') as [time]
          ,T.c.value('./price[1]','money') as [time]
      FROM @ParseXML.nodes('//row') T(c);
      

      【讨论】:

      【解决方案5】:

      XML 存储过程自 SQL 2005 起可用

      基本上,您在过程声明中声明一个 xml 类型的输入参数。

      然后,在您的过程中,您可以使用不同的方法来解析 xml。 也许最简单的方法是使用 OPENXML 方法和 sp_xml_preparedocument/sp_xml_removedocument

      假设你的 xml 变量是这样的:

      <Order>
          <OrderID>12345</OrderID>
          <CustomerID>ABCD-1234</CustomerID>
          <OrderDate>20140101</OrderDate>
      </Order>
      

      程序应该是这样的:

      CREATE PROCEDURE MyProc @xmlData xml
      AS
      
      EXEC sp_xml_preparedocument @i OUTPUT, @xmlData
      
      select *
      from
        openxml (@i, '/ROOT/Order', 1)
        with
        ( OrderID        int
        , CustomerID     nchar(5)
        , OrderDate      datetime)
        INTO MyOrders
      
      EXEC sp_xml_removedocument @i
      

      请参阅:http://technet.microsoft.com/it-it/library/ms186918.aspx 了解如何使用 OPENXML

      【讨论】:

        【解决方案6】:

        虽然 table-valued parameterconstructing XML 是现代方法,但如果您无法使用该方法或者您不希望产生这样的开销,您可以简单地连接多个 INSERT 语句并将它们作为单个批处理发送到 SQL服务器。如果您需要在插入过程中进行一些处理,批处理可以使用a temporary table,在批处理结束时调用的存储过程可以访问它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-26
          相关资源
          最近更新 更多