使用 Select 插入导致 "Subquery returned more than 1 value" 即使子查询 return 预期值

Insert with Select causes "Subquery returned more than 1 value" eventhough subqueries return expected values

使用 MS Sql Server 2008 我正在尝试使用花哨的 Insert/Select 语法将多行插入到 users_roles table 中。执行此查询时,出现错误

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

两个子查询,当它们自己执行时,return 期望值。第一个子查询中有多个记录,第二个子查询中有一个记录。

insert into users_roles(userid, roleid)
        select 
            (select distinct users.id as userID from users 
                inner join users_roles on users.id = users_roles.userid 
                inner join roles on users_roles.roleid = roles.id
                where roles.projectid = 1)
            , 
            (select id as roleID from roles where projectid = 1 and name = 'ALL')

我在这里错过了什么?

导致问题的是第一个子查询中的多行。您按照构建它的方式将其作为一列。如果它 returns 多行 sql 不知道你想要哪一行。

您可能正在寻找类似的东西。

select distinct users.id as userID from users 
inner join users_roles on users.id = users_roles.userid 
inner join roles on users_roles.roleid = roles.id
cross apply 
(
    select id as roleID from roles where projectid = 1 and name = 'ALL'
)
where roles.projectid = 1

您可以使用此语法插入多条记录或单条记录,但不能同时插入!就目前而言,您的查询试图在第一列中 select 多个值,在第二列中尝试一个值。

您不需要两个子查询。只需将您的第一个子查询放入外部查询(returning 多行),然后您的第二个子查询将为每个 return 一行:

insert into users_roles(userid, roleid)
    select distinct users.id as userID,
           (select id as roleID from roles where projectid = 1 and name = 'ALL') as roleID
            from users 
            inner join users_roles on users.id = users_roles.userid 
            inner join roles on users_roles.roleid = roles.id
            where roles.projectid = 1) 

请注意,您并不是真的需要列别名,它们只是为了清楚起见。

SQL 甚至不知道第二个(或第一个)是否会 return 0、1 或许多

decalare @roleID int;
set @roleID = (select top 1 id from roles where projectid = 1 and name = 'ALL');
insert into users_roles(userid, roleid)
select distinct users.id as userID, @roleID 
from users 
inner join users_roles on users.id = users_roles.userid 
inner join roles on users_roles.roleid = roles.id
where roles.projectid = 1;