在条件if / else语句中使用复杂的SQL查询

时间:2016-06-06 19:32:55

标签: sql-server if-statement exists

我正在尝试设置一些SQL测试查询来记录测试在SQL表中是通过还是失败。这些测试查询在几个单独的数据库上运行。以下是使用基本查询的示例(在IF语句中):

DECLARE @dbname NVARCHAR(200);
DECLARE @query NVARCHAR(MAX);

DECLARE db_cursor CURSOR FOR
SELECT name FROM sys.databases
WHERE name LIKE '%JMPTIPR%'

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbname

WHILE @@FETCH_STATUS = 0

BEGIN

SET @query = CAST('
DECLARE @testStatus NVARCHAR(MAX);
DECLARE @name NVARCHAR(MAX);
DECLARE @version NCHAR(10);
DECLARE @testid INT;
DECLARE @repid INT;

SELECT @name = Column1 from [' +@dbname+ '].dbo.Table1
where Column1 = ''File Name''
SELECT @version = attributedata from [' +@dbname+ '].dbo.Table1 
where Column1 = ''Version Number''
SELECT @testid = COALESCE(MAX(TestNum), 0) FROM [Database1].dbo.Table2;
SELECT @repid = RepNum FROM [Database1].dbo.Table2 
WHERE Date = (SELECT MAX(Date) FROM [Database1].dbo.Table2)

IF (
    SELECT COUNT(*)
    FROM [' +@dbname+ '].dbo.Table1
    WHERE [' +@dbname+ '].dbo.Table1.Column1 LIKE ''%execution%''
) IS NOT NULL
    SET @testStatus = ''Test Passed''
ELSE
    SET @testStatus = ''Test Failed''

INSERT INTO [Database1].dbo.Table3 (FileName, Version, Result, Date, TestNum, RepNum)
VALUES (@name, @version, @testStatus, GETDATE(), @testid, @repid)'
AS NVARCHAR(MAX))

EXECUTE (@query)

FETCH NEXT FROM db_cursor INTO @dbname

END
CLOSE db_cursor
DEALLOCATE db_cursor;

问题是我有几个更复杂的查询,我想做同样的事情。我有一个预期的结果,如果一切按计划进行,并且如果出现问题就会产生预期结果,应该返回。所以这是我想要包含的一个更复杂的查询的示例: (值得注意的是,我不希望任何人通过'修复'查询来简单地回答这个问题。我有太多不能在这里提出要修复的人,我宁愿自己学习如何去做。)

SELECT Table1.Column1, Table2.Column2, Table3.Column3,
  Table3.Column4, Table3.Column5, Table3.Column6,
  Table3.Column7
FROM Table2 INNER JOIN
  Table3 ON Table3.Column8 = Table2.id INNER JOIN
  Table1 ON Table2.Column9 = Table1.id
WHERE (Table3.Column5 = -1 AND Table3.Column7 > 0) OR
  (Table3.Column5 = -1 AND Table3.Column6 > 0) OR
  (Table3.Column5 > Table3.Column6 AND Table3.Column6 > 0) OR
  (Table3.Column6 > Table3.Column7 AND Table3.Column7 > 0)

当我将此查询插入我的if语句(并将if条件更改为IS NOT NULL)时,我收到错误消息:

Msg 116, Level 16, State 1, Line 24
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
Msg 116, Level 16, State 1, Line 24
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.

对我来说,似乎最终的问题是我对SQL没有足够深入的理解来使这些工作。

编辑:我看到几条评论说因为我没有显示无法正常运行的代码,所以无法解决问题。我假设你的意思是我提供的示例代码不够具体。

然而,这是我的问题所在。我不希望你修复那个特定的代码。我的问题是关于原始的If / Else代码无法处理某些更复杂的SQL查询(比如带回一个完整表的查询)。

为了给我提供的示例代码提供更多的上下文,它是一个不会带回任何内容的查询(“Test Passed”条件),或者它将带回一个包含多个行和列的表( “测试失败”条件)。我问的是如何将原始查询用于简单查询,并将其调整为不能简单地“计算”或其他简单函数的查询。

2 个答案:

答案 0 :(得分:0)

由于Marc似乎没有兴趣跟进,所以这是你问题的答案。

"复杂性"您的查询与此问题无关。你出于某种原因得到了错误,你也可以从一个非常简单的查询中得到同样的错误。

此查询有效(如您所知):

IF (
    SELECT COUNT(*)
    FROM [' +@dbname+ '].dbo.Table1
    WHERE [' +@dbname+ '].dbo.Table1.Column1 LIKE ''%execution%''
) IS NOT NULL
...

此查询起作用的原因是因为IF()中的子查询返回单个值。伯爵。一行一列。可以测试一个值以查看它是否为NULL,因此没有问题。

此查询不起作用:

IF (
    SELECT Column1, Column2
    FROM [' +@dbname+ '].dbo.Table1
    WHERE [' +@dbname+ '].dbo.Table1.Column1 LIKE ''%execution%''
) IS NOT NULL
...

它不起作用的唯一原因是IF()中的子查询返回多个列,因此不能将此查询的结果与NULL进行比较。也许在你的脑海中有一些你认为它可能会完成的方式(列是NULL,两列都是NULL等),但我向你保证它不能。 SQL引擎不知道如何将结果集(多列)与NULL进行比较。它不是SQL Server的工作方式。它只能将单个标量值与NULL进行比较。

这就是你收到错误的原因:

  

当选择列表中只能指定一个表达式时   子查询不是用EXISTS引入的。

你的"复杂"查询在选择列表中有多个列(表达式)。这是唯一的原因。无论您的查询有多复杂,如果它只返回一列,您可以在IF()语句中使用它,没有任何问题。

查看您的编辑,如果您只需要测试复杂查询是否返回行,那么您可以使用COUNT(*)替换列列表,就像在查询中一样。

答案 1 :(得分:-1)

我无法说出您没有向我们展示的代码,但我可以指出一种更好的方法来执行您所显示的代码。也许它会解决你将它应用到神秘代码时遇到的问题:

这个

IF (
    SELECT COUNT(*)
    FROM [' +@dbname+ '].dbo.Table1
    WHERE [' +@dbname+ '].dbo.Table1.Column1 LIKE ''%execution%'' 
) IS NOT NULL
  SET @testStatus = ''Test Passed''
ELSE
 SET @testStatus = ''Test Failed''

相同
IF EXISTS (
    SELECT 1
    FROM [' +@dbname+ '].dbo.Table1
    WHERE [' +@dbname+ '].dbo.Table1.Column1 LIKE ''%execution%'')
  SET @testStatus = ''Test Passed''
ELSE
  SET @testStatus = ''Test Failed''