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
相关产品推荐
相关产品推荐

