子查询返回多个值

时间:2019-07-19 06:57:40

标签: sql sql-server

我已经创建了一个要在其中插入数据的表。

对于数据插入,已经创建了一个查询,该查询将插入另一个表中的信息。

如果输出是单个值,它将在新表中更新。

但是,如果它是多个值,则会出现错误“子查询返回多个值”

如何使用表中的查询输入多个值?

Declare @BATCHNO as Nvarchar(10)

Declare @PRODNO as Nvarchar(10)

Declare @ISSUENO AS Nvarchar(10)

set @BATCHNO = (select T2.BatchNum  from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14')

Set @PRODNO = (select T1.BaseRef  from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14' )

Set @ISSUENO = (select T1.DocEntry AS 'ISSUE NUMBER' from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14')

Insert Into BATCHDETAIL (BATCHNO,PRODNO,ISSUENO) Values(@BATCHNO,@PRODNO,@ISSUENO)

  

[Microsoft] [用于SQL Server的ODBC驱动程序13] [SQL Server]子查询返回了多个值。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做。在查询名称为“ FMS_BATCHNO_UPDATE”的字段“ U_EA_LICENCE”上执行FMS失败

3 个答案:

答案 0 :(得分:2)

您需要修复子查询,以便它们返回要插入的确切单个值。

例如,如果您不太在意并可以插入满足这些条件的任何值,则只需在子查询中添加TOP 1,这样它们将仅返回可用的第一个值。

Declare @BATCHNO as Nvarchar(10)   
Declare @PRODNO as Nvarchar(10)
Declare @ISSUENO AS Nvarchar(10)

set @BATCHNO = (select TOP 1 T2.BatchNum  from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14')

Set @PRODNO = (select TOP 1 T1.BaseRef  from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14' )

Set @ISSUENO = (select TOP 1 T1.DocEntry AS 'ISSUE NUMBER' from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14')

Insert Into BATCHDETAIL (BATCHNO,PRODNO,ISSUENO) Values(@BATCHNO,@PRODNO,@ISSUENO)

通过这种方式,您可以简化在单个查询中分配三个变量的脚本:

Declare @BATCHNO as Nvarchar(10)    
Declare @PRODNO as Nvarchar(10)    
Declare @ISSUENO AS Nvarchar(10)

select TOP 1 @BATCHNO = T2.BatchNum,
             @PRODNO = T1.BaseRef,
             @ISSUENO = T1.DocEntry
from OWOR T0 
     INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
     INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
where T0.DocEntry = '14'   

Insert Into BATCHDETAIL (BATCHNO,PRODNO,ISSUENO) Values(@BATCHNO,@PRODNO,@ISSUENO)

最后,如果要插入满足条件的所有值,则可以使用select代替插入所有的值,而不用TOP 1取第一个值:

Insert Into BATCHDETAIL (BATCHNO,PRODNO,ISSUENO)     
       select T2.BatchNum, T1.BaseRef, T1.DocEntry
       from OWOR T0 
            INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
            INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
       where T0.DocEntry = '14'   

答案 1 :(得分:2)

您似乎正在尝试根据现有数据插入多行。在这种情况下,您应该使用INSERT .. SELECT而不是INSERT...VALUES

INSERT BatchDetail (BatchNo, ProdNo, IssueNo)
SELECT  T2.BatchNum, T1.BaseRef, T1.DocEntry
FROM    OWOR T0 
        INNER JOIN table_P T1 
            ON T0.DocEntry = T1.BaseEntry
        INNER JOIN Table_I T2 
            ON T1.DocEntry = T2.BaseEntry 
            AND T1.ObjType = T2.BaseType
WHERE   T0.DocEntry = '14';

如果您只想基于多个记录插入一条记录,则可以使用TOP 1,并提供ORDER BY以确保获得可重复的结果:

INSERT BatchDetail (BatchNo, ProdNo, IssueNo)
SELECT  TOP 1 T2.BatchNum, T1.BaseRef, T1.DocEntry
FROM    OWOR T0 
        INNER JOIN table_P T1 
            ON T0.DocEntry = T1.BaseEntry
        INNER JOIN Table_I T2 
            ON T1.DocEntry = T2.BaseEntry 
            AND T1.ObjType = T2.BaseType
WHERE   T0.DocEntry = '14'
ORDER BY t2.BatchNum, T1.BaseRef, T1.DocEntry;

最后,如果您确实确实想要3个标量变量,那么您仍然可以使用SELECTTOP 1,只需使用SELECT进行变量分配:

DECLARE @BATCHNO AS NVARCHAR(10)
        @PRODNO AS NVARCHAR(10)
        @ISSUENO AS NVARCHAR(10);

SELECT  TOP 1
        @BATCHNO = T2.BatchNum, 
        @PRODNO = T1.BaseRef, 
        @ISSUENO = T1.DocEntry
FROM    OWOR T0 
        INNER JOIN table_P T1 
            ON T0.DocEntry = T1.BaseEntry
        INNER JOIN Table_I T2 
            ON T1.DocEntry = T2.BaseEntry 
            AND T1.ObjType = T2.BaseType
WHERE   T0.DocEntry = '14'
ORDER BY t2.BatchNum, T1.BaseRef, T1.DocEntry;

ADENDUMEM

我非常建议您不要使用任何使用3个带有{​​{1}}并且没有排序依据的查询的方法。例如,如果您有一个表:

TOP 1

您可能希望它分配与单个记录对应的@ A,@ B和@C值(例如A B C ---------- 1 3 2 2 1 3 3 2 1 1, 3, 2

2, 1, 3

但是,您要执行3个不同的查询,并且根据表上的索引,您可以获得3个不同的查询计划和3个不同的记录用于每次分配。

这很容易证明:

SET @A = (SELECT TOP 1 A FROM #T);
SET @B = (SELECT TOP 1 B FROM #T);
SET @C = (SELECT TOP 1 C FROM #T);

对我来说,这返回:

-- CREATE TABLE AND FILL IT 
IF OBJECT_ID(N'tempdb..#T', 'U') IS NOT NULL DROP TABLE #T;

CREATE TABLE #T (A INT NOT NULL PRIMARY KEY, B INT NOT NULL, C INT NOT NULL);

CREATE NONCLUSTERED INDEX IX_T_B ON #T (B);
CREATE NONCLUSTERED INDEX IX_T_C ON #T (C);

INSERT #T (A, B, C) 
VALUES (1, 3, 2), (2, 1, 3), (3, 2, 1);

DECLARE @A INT, @B INT, @C INT;

SET @A = (SELECT TOP 1 A FROM #T);
SET @B = (SELECT TOP 1 B FROM #T);
SET @C = (SELECT TOP 1 C FROM #T);

SELECT A = @A, B = @B, C = @C;

与原始数据中的任何记录都不对应。这可能完全适合您的需求,但是绝对需要注意。

Example on db<>fiddle

答案 2 :(得分:1)

使用它。

Declare @BATCHNO as Nvarchar(10)

Declare @PRODNO as Nvarchar(10)

Declare @ISSUENO AS Nvarchar(10)

set @BATCHNO = (select TOP 1 T2.BatchNum  from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14')

Set @PRODNO = (select TOP 1 T1.BaseRef  from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14' )

Set @ISSUENO = (select TOP 1 T1.DocEntry AS 'ISSUE NUMBER' from OWOR T0 INNER JOIN table_P T1 ON T0.DocEntry = T1.BaseEntry
              INNER JOIN Table_I T2 ON T1.DocEntry = T2.BaseEntry AND T1.ObjType = T2.BaseType
              WHERE T0.DocEntry = '14')

Insert Into BATCHDETAIL (BATCHNO,PRODNO,ISSUENO) Values(@BATCHNO,@PRODNO,@ISSUENO)
相关问题