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

SQL Server存储过程报错:Subquery returned more than 1 value 求助

解决SQL Server存储过程的“Subquery returned more than 1 value”错误

问题原因分析

你遇到的这个错误根源非常明确——就是存储过程里的这行代码:

SET @Users_Id = (SELECT Id FROM Users)

当Users表中有多条记录时,这个子查询会返回一堆Id值,但变量@Users_Id只能存单个整数,SQL Server根本没法把多个值塞进一个变量里,自然就抛出了这个错误。

而且你的逻辑还有个漏洞:IF EXISTS (SELECT Id FROM Users)只是判断Users表有没有数据,哪怕有数据,也完全没明确要取哪个用户的ID关联到Rent表,这逻辑本身就不成立。

解决方案

你需要明确指定要关联的用户ID,通常这个场景下,要么传当前登录用户的ID,要么在存储过程里新增参数接收用户ID。下面给你两种常用的处理方式:

方式1:新增@Users_Id参数(推荐,逻辑更清晰)

直接修改存储过程,让它接收前端传入的用户ID,这样能精准关联到指定用户:

CREATE PROCEDURE [dbo].[insert_rent] 
    @comment_info NVARCHAR(MAX), 
    @booth_size NVARCHAR(MAX), 
    @customer_type NVARCHAR(MAX), 
    @booth_type NVARCHAR(MAX), 
    @customer_email TEXT, 
    @customer_mobile TEXT,
    @Users_Id INT -- 新增用户ID参数
AS
BEGIN
    -- 直接用传入的用户ID执行插入
    INSERT INTO Rent (rent_comments, booth_size, customer_type, booth_type, customer_email, customer_mobile, Users_id)
    VALUES (@comment_info, @booth_size, @customer_type, @booth_type, @customer_email, @customer_mobile, @Users_Id)
END

然后调整你的ASP.NET代码,添加这个参数(这里假设你能从登录状态获取当前用户ID,比如用User.Identity.GetUserId(),如果是整数类型的话):

String CS = ConfigurationManager.ConnectionStrings["BoothsConnectionString1"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
    using (SqlCommand cmd = new SqlCommand("insert_rent", con)) // 给SqlCommand也套上using,避免资源泄漏
    {
        cmd.CommandType = CommandType.StoredProcedure;
        con.Open();

        cmd.Parameters.Add("@comment_info", SqlDbType.NVarChar).Value = comment_input.Text;
        cmd.Parameters.Add("@booth_size", SqlDbType.NVarChar).Value = size_dropwdown.SelectedValue.ToString();
        cmd.Parameters.Add("@customer_type", SqlDbType.NVarChar).Value = customer_type_dropdown.SelectedValue.ToString();
        cmd.Parameters.Add("@booth_type", SqlDbType.NVarChar).Value = booth_type_dropdown.SelectedValue.ToString();
        cmd.Parameters.Add("@customer_email", SqlDbType.NVarChar).Value = customer_email.Value;
        cmd.Parameters.Add("@customer_mobile", SqlDbType.NVarChar).Value = customer_mobilenumber.Value; // 建议把NText换成NVARCHAR(MAX),TEXT/NTEXT是过时类型
        // 添加用户ID参数,替换成你实际获取当前用户ID的逻辑
        cmd.Parameters.Add("@Users_Id", SqlDbType.Int).Value = Convert.ToInt32(User.Identity.GetUserId()); 

        cmd.ExecuteNonQuery();
    }
}

方式2:根据用户邮箱匹配(无登录状态时用)

如果你的场景没有登录状态,想通过传入的@customer_email去Users表匹配对应的用户ID,可以这么改存储过程:

CREATE PROCEDURE [dbo].[insert_rent] 
    @comment_info NVARCHAR(MAX), 
    @booth_size NVARCHAR(MAX), 
    @customer_type NVARCHAR(MAX), 
    @booth_type NVARCHAR(MAX), 
    @customer_email TEXT, 
    @customer_mobile TEXT
AS
BEGIN
    DECLARE @Users_Id INT
    -- 根据邮箱获取唯一用户ID(必须确保Users表的Email字段是唯一的!)
    SELECT @Users_Id = Id FROM Users WHERE Email = @customer_email

    -- 找到用户再插入,没找到就抛出提示
    IF @Users_Id IS NOT NULL
    BEGIN
        INSERT INTO Rent (rent_comments, booth_size, customer_type, booth_type, customer_email, customer_mobile, Users_id)
        VALUES (@comment_info, @booth_size, @customer_type, @booth_type, @customer_email, @customer_mobile, @Users_Id)
    END
    ELSE
    BEGIN
        RAISERROR('未找到匹配的用户记录', 16, 1)
    END
END

这种方式一定要保证Users表的Email字段是唯一约束的,不然还是会触发同样的多值错误。

额外小提醒

  • 尽量把存储过程和代码里的TEXT/NTEXT类型换成NVARCHAR(MAX),这俩是SQL Server的过时类型,官方早就不推荐用了。
  • 记得给SqlCommand也加上using块,避免数据库连接泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:23:32