如果列存在,则选择columnValue,否则返回null

Ste*_*ler 36 sql sql-server select exists

我想知道如果列存在,我是否可以选择列的值,否则只选择null.换句话说,我想"提升"select语句来处理列不存在时的情况.

SELECT uniqueId
    ,  columnTwo
    ,  /*WHEN columnThree exists THEN columnThree ELSE NULL END*/ AS columnThree
FROM (subQuery) s
Run Code Online (Sandbox Code Playgroud)

请注意,我正在努力巩固我的数据模型和设计.我希望在未来几周内排除这种逻辑,但我真的想超越这个问题,因为数据模型修复比我现在要解决的更耗费时间.

另请注意,我希望能够在一个查询中执行此操作.所以我不是在寻找像这样的答案

首先检查子查询中的列.然后修改您的查询以适当地处理子查询中的列.

Gor*_*off 30

您不能使用简单的SQL语句执行此操作.除非表中存在所有表和列引用,否则不会编译SQL查询.

如果"子查询"是表引用或视图,则可以使用动态SQL执行此操作.

在动态SQL中,您可以执行以下操作:

declare @sql nvarchar(max) = '
SELECT uniqueId, columnTwo, '+
    (case when exists (select *
                       from INFORMATION_SCHEMA.COLUMNS 
                       where tablename = @TableName and
                             columnname = 'ColumnThree' -- and schema name too, if you like
                      )
          then 'ColumnThree'
          else 'NULL as ColumnThree'
     end) + '
FROM (select * from '+@SourceName+' s
';

exec sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

对于实际的子查询,您可以通过检查子查询是否返回具有该列名称的内容来近似相同的事物.一种方法是运行查询: select top 0 * into #temp from (<subquery>) s然后检查列中的列#temp.

  • @Gordon +1虽然它**可以完成**(请参阅我的答案“CROSS APPLY”) (2认同)

ype*_*eᵀᴹ 20

正如其他人已经建议的那样,理智的方法是使查询符合您的表格设计.

有一种相当奇特的方法来实现你想要的(纯粹的,非动态的)SQL.在DBA.SE上发布了类似的问题:如果列存在则如何选择特定行;如果列不存在则如果选择所有行但由于只需要一行和一列,因此它更简单.你的问题更复杂,所以查询更复杂,至少可以说.这是疯狂的做法:

; WITH s AS
  (subquery)                                    -- subquery
SELECT uniqueId
    ,  columnTwo
    ,  columnThree =
       ( SELECT ( SELECT columnThree 
                  FROM s AS s2
                  WHERE s2.uniqueId = s.uniqueId
                ) AS columnThree
         FROM (SELECT NULL AS columnThree) AS dummy
       )
FROM s ;
Run Code Online (Sandbox Code Playgroud)

它还假定uniqueId子查询的结果集中是唯一的.

SQL-Fiddle测试


还有一个更简单的方法,它具有额外的优势,允许多个列具有单个子查询:

SELECT s.*     
FROM
    ( SELECT NULL AS columnTwo,
             NULL AS columnThree,
             NULL AS columnFour
    ) AS dummy 
  CROSS APPLY
    ( SELECT 
          uniqueId,
          columnTwo,
          columnThree,
          columnFour
      FROM tableX
    ) AS s ;
Run Code Online (Sandbox Code Playgroud)

这个问题也在DBA.SE上被提出并且已经被@Andriy M(也使用CROSS APPLY了!)和Michael Ericsson(使用XML)回答:
为什么我不能使用CASE语句来查看列是否存在而不是从中选择SELECT ?

  • @ypercubeᵀᴹ...这非常聪明,使用作用域规则来处理不存在的列.奖励! (2认同)

Rez*_*abi 5

您可以使用动态 SQL。

首先您需要检查存在,然后创建动态查询。

DECLARE @query NVARCHAR(MAX) = '
SELECT FirstColumn, SecondColumn, '+
  (CASE WHEN exists (SELECT 1 FROM syscolumns 
  WHERE name = 'ColumnName' AND id = OBJECT_ID('TableName'))
      THEN 'ColumnName'
      ELSE 'NULL as ThreeColumn'
   END) + '
FROM TableName'

EXEC sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)