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

如何从C#应用调用SQL Server序列生成16位ID并插入数据

问题描述

C#应用需调用自行创建的SQL Server序列生成16位ID,并将该ID与其他字段数据插入指定数据表。在SQL Server Management Studio中执行SQL语句可正常插入,但编写C#代码时出现**“需声明标量变量@DMZCode”**的错误。

可用SQL语句(SSMS中正常运行)

DECLARE @Location VARCHAR(4);
DECLARE @Year VARCHAR(4);
DECLARE @DMZ INT;
DECLARE @DMZCode VARCHAR(16);

SET @Location = '0010'; -- 修正原代码笔误:@Plant应为@Location
SET @Year = YEAR(GETDATE());
SET @DMZ = (NEXT VALUE FOR [dbo].[CountDMZCode]);

SET @DMZCode = CAST(RIGHT(CONCAT('0000' ,@Location),4) + RIGHT(CONCAT('00', @Year),2) + RIGHT(CONCAT('0000000000', @DMZ), 10) AS VARCHAR(16))

INSERT INTO dbo.tblNameHere
(DMZ_id,matnumber,mach_name,station,value_name,num_value)
VALUES
(@DMZCode, '11.22.556','filling mach 1','transfer','weight','250.4');

尝试的C#代码(报错)

string stri = ConfigurationManager.ConnectionStrings["connectiontodatabase"].ConnectionString;

SqlConnection con = new SqlConnection(stri);
con.Open();

String query = "INSERT INTO dbo.tblNameHere" +
                "(DMZ_id, matnumber, mach_name, station, value_name, num_value) VALUES (@DMZCode, '10.887.400', 'filling machine 1', 'transfer', 'weight', '250.4')";

if (con.State == ConnectionState.Open)
{
    SqlCommand cmmd = new SqlCommand(query, con);
            
    try
    {
        cmmd.ExecuteNonQuery();

        DialogResult result = MessageBox.Show("Data saved successfully", "Information",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch (SqlException expe)
    {
        MessageBox.Show(expe.Message);
        con.Dispose();
    }
} 

错误原因

你的C#代码仅在INSERT语句中引用了@DMZCode变量,但既没有在SQL语句中包含生成该变量的核心逻辑(调用序列、拼接字符串),也没有通过SqlParameter给这个变量赋值,导致SQL Server无法识别该标量变量。


正确实现方法

方法1:将ID生成逻辑完全放在SQL语句中(推荐)

把生成@DMZCode的逻辑直接整合到SQL脚本中,所有操作在数据库端执行,避免客户端与数据库的额外交互,同时保证逻辑一致性。

string stri = ConfigurationManager.ConnectionStrings["connectiontodatabase"].ConnectionString;

// 整合ID生成逻辑的完整SQL语句
string query = @"DECLARE @Location VARCHAR(4);
DECLARE @Year VARCHAR(4);
DECLARE @DMZ INT;
DECLARE @DMZCode VARCHAR(16);

SET @Location = '0010';
SET @Year = YEAR(GETDATE());
SET @DMZ = (NEXT VALUE FOR [dbo].[CountDMZCode]);

SET @DMZCode = CAST(RIGHT(CONCAT('0000' ,@Location),4) + RIGHT(CONCAT('00', @Year),2) + RIGHT(CONCAT('0000000000', @DMZ), 10) AS VARCHAR(16))

INSERT INTO dbo.tblNameHere
(DMZ_id, matnumber, mach_name, station, value_name, num_value)
VALUES
(@DMZCode, '10.887.400', 'filling machine 1', 'transfer', 'weight', '250.4');";

using (SqlConnection con = new SqlConnection(stri))
{
    using (SqlCommand cmmd = new SqlCommand(query, con))
    {
        try
        {
            con.Open();
            cmmd.ExecuteNonQuery();
            MessageBox.Show("数据保存成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        catch (SqlException expe)
        {
            MessageBox.Show(expe.Message);
        }
    }
}

优化点说明

  • 使用using语句自动释放连接和命令资源,无需手动调用Dispose
  • 修正原SQL中的笔误,避免变量未定义错误

方法2:在C#中生成ID后通过参数传递

如果需要在C#端处理ID生成逻辑,可以先调用序列获取值,拼接成16位ID,再通过SqlParameter传递给INSERT语句。

string stri = ConfigurationManager.ConnectionStrings["connectiontodatabase"].ConnectionString;
string dmzCode = string.Empty;

using (SqlConnection con = new SqlConnection(stri))
{
    con.Open();
    // 先获取序列的下一个值
    using (SqlCommand seqCmd = new SqlCommand("SELECT NEXT VALUE FOR [dbo].[CountDMZCode];", con))
    {
        int dmz = (int)seqCmd.ExecuteScalar();
        string location = "0010";
        string year = DateTime.Now.Year.ToString().Substring(2, 2); // 取年份后两位
        // 拼接生成16位ID
        dmzCode = $"{location.PadLeft(4, '0')}{year.PadLeft(2, '0')}{dmz.ToString().PadLeft(10, '0')}";
    }

    // 执行插入操作
    string insertQuery = @"INSERT INTO dbo.tblNameHere
(DMZ_id, matnumber, mach_name, station, value_name, num_value)
VALUES
(@DMZCode, '10.887.400', 'filling machine 1', 'transfer', 'weight', '250.4');";

    using (SqlCommand insertCmd = new SqlCommand(insertQuery, con))
    {
        // 添加参数并赋值,解决变量未声明问题
        insertCmd.Parameters.AddWithValue("@DMZCode", dmzCode);
        try
        {
            insertCmd.ExecuteNonQuery();
            MessageBox.Show("数据保存成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        catch (SqlException expe)
        {
            MessageBox.Show(expe.Message);
        }
    }
}

说明

  • 先通过单独SQL命令获取序列值,再在C#端完成字符串拼接
  • 使用SqlParameter传递变量,避免SQL注入风险,同时解决标量变量未声明的错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:31:13