2

我在前端有一个 Gridview,其中 Grid 有两列:ID 和 Order,如下所示:

 ID        Order

 1           1
 2           2
 3           3
 4           4

现在用户可以像在前端 Gridview 中一样更新订单:

ID        Order

 1           2
 2           4
 3           1
 4           3

现在,如果用户单击保存按钮,则 ID 和订单数据将作为 @sID = (1,2,3,4) 和 @sOrder = (2,4,1,3) 发送到存储过程

现在,如果我想更新订单并进行保存,我想将其存储到数据库中。通过存储过程如何更新到表中,以便更新表,而选择它给我的结果如下:

ID        Order

 1           2
 2           4
 3           1
 4           3
4

3 回答 3

1

您可以使用表值参数来避免将分隔符分隔的值甚至 XML 发送到数据库。为此,您需要:

  1. 在数据库中声明一个参数类型,如下所示:

    CREATE TYPE UpdateOrderType TABLE (ID int, Order int)
    
  2. 之后,您可以定义将参数用作的过程

    CREATE PROCEDURE UpdateOrder (@UpdateOrderValues UpdateOrderType readonly)
    AS
    BEGIN
      UPDATE t
        SET OrderID = tvp.Order
        FROM <YourTable> t
          INNER JOIN @UpdateOrderValues tvp ON t.ID=tvp.ID
    END
    

    如您所见,与解析 XML 或分隔字符串相比,SQL 是微不足道的。

  3. 使用 C# 中的参数:

    using (SqlCommand command = connection.CreateCommand()) {
      command.CommandText = "dbo.UpdateOrder";
      command.CommandType = CommandType.StoredProcedure;
    
      //create a table from your gridview data
      DataTable paramValue = CreateDataTable(orderedData) 
      SqlParameter parameter = command.Parameters
                                .AddWithValue("@UpdateOrderValues", paramValue );
      parameter.SqlDbType = SqlDbType.Structured;
      parameter.TypeName = "dbo.UpdateOrderType";
    
      command.ExecuteNonQuery();
    }
    

    CreateDataTable类似的东西在哪里:

    //assuming the source data has ID and Order properties
    private static DataTable CreateDataTable(IEnumerable<OrderData> source) {
      DataTable table = new DataTable();
      table.Columns.Add("ID", typeof(int));
      table.Columns.Add("Order", typeof(int));
      foreach (OrderData data in source) {
          table.Rows.Add(data.ID, data.Order);
      }
      return table;
    }
    

    (从这个问题中提取的代码)

正如您所见,这种方法(特定于 SQL-Server 2008 及更高版本)使得将结构化数据作为参数传递给过程变得更容易、更正式。更重要的是,您一直在使用类型安全,所以在字符串/xml 操作中往往会出现的许多解析错误都不是问题。

于 2013-02-04T08:17:29.710 回答
1

没有内置函数来解析这些逗号分隔的字符串。但是,您可以使用 SQL Server 中的 XML 函数来执行此操作。就像是:

DECLARE @sID VARCHAR(100) = '1,2,3,4';
DECLARE @sOrder VARCHAR(10) = '2,4,1,3';

DECLARE @sIDASXml xml = CONVERT(xml,
                            '<root><s>' + 
                            REPLACE(@sID, ',', '</s><s>') + 
                            '</s></root>');

DECLARE @sOrderASXml xml = CONVERT(xml,
                        '<root><s>' + 
                        REPLACE(@sOrder, ',', '</s><s>') + 
                        '</s></root>');

;WITH ParsedIDs
AS
(
    SELECT ID = T.c.value('.','varchar(20)'),
    ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS RowNumber
    FROM @sIDASXml.nodes('/root/s') T(c)
), ParsedOrders
AS
(
    SELECT "Order" = T.c.value('.','varchar(20)'),
        ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS RowNumber
    FROM @sOrderASXml.nodes('/root/s') T(c)
)
UPDATE t
SET t."Order" = p."Order"
FROM @tableName AS t
INNER JOIN
(
   SELECT i.ID, p."Order"
   FROM ParsedOrders p 
   INNER JOIN ParsedIDs i ON p.RowNumber = i.RowNumber
) AS p ON t.ID = p.ID;

现场演示

然后你可以把它放在一个存储过程或任何东西中。

请注意:您不需要手动执行所有这些操作,应该通过某种方式使该gridview通过数据绑定自动更新底层数据表。你应该寻找这样的东西,而不是所有这些痛苦。

于 2013-02-04T07:01:37.577 回答
0

您可以使用 charindex 之类的

DECLARE @id VARCHAR(MAX)
DECLARE @order VARCHAR(MAX)

SET @id='1,2,3,4,'
SET @order='2,4,1,3,'

WHILE CHARINDEX(',',@id) > 0
BEGIN
DECLARE @tmpid VARCHAR(50)
SET @tmpid=SUBSTRING(@id,1,(charindex(',',@id)-1))
DECLARE @tmporder VARCHAR(50)
SET @tmporder=SUBSTRING(@order,1,(charindex(',',@order)-1))

UPDATE dbo.Test SET
[Order]=@tmporder
WHERE ID=convert(int,@tmpid)

SET @id = SUBSTRING(@id,charindex(',',@id)+1,len(@id))
SET @order=SUBSTRING(@order,charindex(',',@order)+1,len(@order))
END
于 2013-02-04T08:08:07.960 回答