简体   繁体   中英

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=,

I am trying to read multiple values from parameter, store it in a variable and later use it in the select statement to pull multiple values.

declare @codes XML = N'<Root>
                          <List Value="120" />
                          <List Value="110" />
                         </Root>';

declare @codeList VARCHAR(MAX) = (SELECT T.Item.value('@Value[1]','VARCHAR(MAX)')  FROM  @codes.nodes('/Root/List') AS T(Item));

WITH CODE_RESULT AS(      
       SELECT  ID, Name, Region,
                 FROM dbo.MyTable1    
                 WHERE
                 (@codes IS NULL OR DataCode IN ( @codeList))

       ...

       UNION

       SELECT  ID, Name, Region,
                 FROM dbo.MyTable2    
                 WHERE
                 (@codes IS NULL OR DataCode IN ( @codeList))

       ...

But, I am getting the following exception:

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

Expectation:

How do I store the parameter values in a variable and later reuse it in multiple select statements under 'in' clause? Any suggestion is appreciated.

If you need to store multiple values for use later, use a TABLE VARIABLE to hold the results, like this:

DECLARE @dataCodes TABLE (DataCode varchar(MAX));
INSERT INTO @dataCodes
    SELECT T.Item.value('@Value[1]', 'varchar(max)')
      FROM @codes.nodes('/Root/List') AS T(Item);

You can then use the " WHERE DataCode IN (SELECT DataCode FROM @dataCodes) " to do the select and get all the results.

Your problem is here:

declare @codeList VARCHAR(MAX) = (SELECT T.Item.value('@Value[1]','VARCHAR(MAX)')  FROM  @codes.nodes('/Root/List') AS T(Item));

Your select returns two results (120, 110), but a scalar VARCHAR variable can only hold one.

You can fix it by creating a table variable:

DECLARE @codeList TABLE (code varchar(100));
INSERT @codeList 
SELECT  
  T.Item.value('@Value[1]','VARCHAR(MAX)')  
FROM  @codes.nodes('/Root/List') AS T(Item);

And then change (@codes IS NULL OR DataCode IN ( @codeList)) to (@codes IS NULL OR DataCode IN (SELECT code FROM @codeList))

Here, a LEFT JOIN should perform better than your current syntax, eg

WITH CODE_RESULT AS(      
  SELECT  ID, Name, Region,
  FROM dbo.MyTable1  t1 
  LEFT JOIN @codeList  cl
  ON t1.DataCode = cl.code

You may have to add additional logic to check if cl.code is null depending on your intentions.

You create a table variable

SQL Fiddle Demo

Declare @T_variable table(name varchar(200));

insert into @T_variable 
SELECT ID FROM Table1;

SELECT *
FROM YourTable
WHERE ID NOT IN
   (SELECT *
    FROM @T_variable)
;

GO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM