我想知道如果列存在,我是否可以选择列的值,否则只选择null。换句话说,我想“解除”select语句来处理列不存在时的情况。
SELECT uniqueId
, columnTwo
, /*WHEN columnThree exists THEN columnThree ELSE NULL END*/ AS columnThree
FROM (subQuery) s
注意,我正在努力巩固我的数据模型和设计。我希望在未来几周内排除这种逻辑,但我真的想超越这个问题,因为数据模型修复比我现在要解决的问题更耗时。
另请注意,我希望能够在一个查询中执行此操作。所以我不是在寻找像
这样的答案首先检查子查询中的列。然后修改你的 查询以适当处理子查询中的列。
答案 0 :(得分:24)
您无法使用简单的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;
对于实际的子查询,您可以通过检查子查询是否返回具有该列名称的内容来近似相同的事物。一种方法是运行查询:select top 0 * into #temp from (<subquery>) s
,然后检查#temp
中的列。
答案 1 :(得分:16)
正如其他人已经建议的那样,理智的方法是使查询符合您的表设计。
有一种相当奇特的方法来实现你想要的(纯粹的,非动态的)SQL。类似的问题发布在DBA.SE:How to select specific rows if a column exists or all rows if a column doesn't但是它更简单,因为只需要一行和一列。你的问题更复杂,所以查询更复杂,至少可以说。这是疯狂的方法:
; 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 ;
它还假定uniqueId
在子查询的结果集中是唯一的。
一种更简单的方法,它具有额外的优势,允许多个列具有单个子查询:
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 ;
此问题也在DBA.SE上提出,并且@Andriy M已经回答了问题(也使用了CROSS APPLY
!)和Michael Ericsson(使用XML
):
Why can't I use a CASE statement to see if a column exists and not SELECT from it?
答案 2 :(得分:1)
您可以使用动态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;