You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从SQL中提取最后一条数据加1后重新存入数据库(C# WPF实现)

实现方案(C# WPF + SQL 订单编号自增生成)

注意:不建议直接在C#端单独查询最后一条数据再加1,高并发场景下会出现订单号重复问题,优先推荐SQL端原子操作方案,保证数据一致性。


前置依赖

首先安装对应NuGet包,优先用新版SQL客户端:

  • 包名:Microsoft.Data.SqlClient
  • 若使用.NET Framework环境可以用旧版System.Data.SqlClient

方案1:SQL端原子操作(推荐,支持高并发)

该方案将查询、自增、返回逻辑封装在单条SQL语句中,全程原子性,不会出现重复编号问题。
假设业务表结构如下:

  • 表名:DeliveryOrders
  • 需自增字段:OrderNo(订单号,示例格式为202405200001,前8位为日期,后4位为当日流水号)

核心代码示例:

using Microsoft.Data.SqlClient;
using System;

// 订单号生成方法
public string GenerateNewOrderNo()
{
    // 替换为自身业务的数据库连接字符串
    string connString = "Server=你的数据库地址;Database=你的库名;Uid=账号;Pwd=密码;TrustServerCertificate=True;";
    string newOrderNo = string.Empty;

    // SQL原子逻辑:查询当日最大订单号→无则默认首单→有则流水号+1→返回新编号
    string sql = @"
DECLARE @datePrefix VARCHAR(8) = CONVERT(VARCHAR(8), GETDATE(), 112);
DECLARE @maxOrderNo VARCHAR(20);
DECLARE @newOrderNo VARCHAR(20);

SELECT @maxOrderNo = MAX(OrderNo) 
FROM DeliveryOrders 
WHERE OrderNo LIKE @datePrefix + '%';

IF @maxOrderNo IS NULL
    SET @newOrderNo = @datePrefix + '0001';
ELSE
    SET @newOrderNo = @datePrefix + RIGHT('0000' + CAST(CAST(RIGHT(@maxOrderNo, 4) AS INT) + 1 AS VARCHAR(4)), 4);

-- 若需要直接插入完整订单数据,可在此处补充INSERT语句,进一步保证原子性
-- INSERT INTO DeliveryOrders (OrderNo, ReceiverName, CreateTime) VALUES (@newOrderNo, @receiver, GETDATE());

SELECT @newOrderNo;
";

    using (SqlConnection conn = new SqlConnection(connString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            newOrderNo = cmd.ExecuteScalar()?.ToString();
        }
    }
    return newOrderNo;
}

方案2:C#端查改分离(仅低并发单实例场景使用)

如果业务并发量极低,不存在同时生成订单的场景,可以使用该更直观的方案:

public string GenerateNewOrderNoLowConcurrency()
{
    string connString = "你的数据库连接字符串";
    string datePrefix = DateTime.Now.ToString("yyyyMMdd");
    int newSerial = 1;

    using (SqlConnection conn = new SqlConnection(connString))
    {
        conn.Open();
        // 第一步:查询当日最后一条订单号
        string querySql = @"SELECT TOP 1 OrderNo FROM DeliveryOrders WHERE OrderNo LIKE @prefix + '%' ORDER BY OrderNo DESC";
        using (SqlCommand queryCmd = new SqlCommand(querySql, conn))
        {
            queryCmd.Parameters.AddWithValue("@prefix", datePrefix);
            var result = queryCmd.ExecuteScalar();
            if (result != null)
            {
                string lastOrderNo = result.ToString();
                // 截取流水号加1
                string lastSerialStr = lastOrderNo.Substring(lastOrderNo.Length - 4, 4);
                if (int.TryParse(lastSerialStr, out int lastSerial))
                {
                    newSerial = lastSerial + 1;
                }
            }
        }

        // 生成新订单号
        string newOrderNo = $"{datePrefix}{newSerial.ToString().PadLeft(4, '0')}";

        // 第二步:插入新订单数据到数据库
        string insertSql = @"INSERT INTO DeliveryOrders (OrderNo, CreateTime, ReceiverName) VALUES (@OrderNo, @CreateTime, @ReceiverName)";
        using (SqlCommand insertCmd = new SqlCommand(insertSql, conn))
        {
            insertCmd.Parameters.AddWithValue("@OrderNo", newOrderNo);
            insertCmd.Parameters.AddWithValue("@CreateTime", DateTime.Now);
            insertCmd.Parameters.AddWithValue("@ReceiverName", "收件人信息");
            insertCmd.ExecuteNonQuery();
        }
        return newOrderNo;
    }
}

WPF UI绑定示例

生成的订单号可以直接赋值到WPF控件显示:

// 按钮点击生成订单号示例
private void BtnCreateOrder_Click(object sender, RoutedEventArgs e)
{
    string newOrderNo = GenerateNewOrderNo();
    // 赋值给前端文本框显示
    TxtOrderNo.Text = newOrderNo;
}

优化建议

  • 若业务并发量很高,可以单独维护一张序号配置表,专门存储各业务线的当前最大序号,更新时加行锁,性能比每次查询全订单表更高
  • 流水号位数可根据单日订单量调整,超过1万单可改为5位或6位
  • 所有SQL操作都使用参数化查询,避免SQL注入风险

内容的提问来源于stack exchange,提问作者Ascenal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 22:24:02