SQL - 如果 OLEQuery 中存在,则选择列

Posted

技术标签:

【中文标题】SQL - 如果 OLEQuery 中存在,则选择列【英文标题】:SQL - select column if exists in OLEQuery 【发布时间】:2017-04-07 10:27:35 【问题描述】:

在某些客户中,我使用较旧的数据库,但现在我必须为新客户添加另一列。我的程序现在将查询新列是否存在,如果不存在则使用 NULL。

到目前为止,使用 C# 和 OLEQuery 可以正常工作:

string sql = @"SELECT i.[ID] AS cID, 
                        pg.[Name], 
                        pg.[ID] AS pgid, 
                        i.[time],
                        defect = CASE i.[defect] WHEN 0 THEN 'OK' WHEN 1 THEN 'NOK' END,                                           
                  FROM inspection AS i WITH (NOLOCK) INNER JOIN programs as pg ON i.programid = pg.[ID]
                  WHERE i.[time] BETWEEN ... ///SOME MORE CODE IS FOLLOWING HERE!
                    ";

但现在我想在其中添加(可能/可能不)现有列 timeTo。

string sql = @"SELECT i.[ID] AS cID, 
                        pg.[Name], 
                        pg.[ID] AS pgid, 
                        i.[time],
                        defect = CASE i.[defect] WHEN 0 THEN 'OK' WHEN 1 THEN 'NOK' END,                      
                        timeTo = CASE i.[timeTo] WHEN EXISTS THEN i.[timeTo] ELSE NULL END                     
                  FROM inspection AS i WITH (NOLOCK) INNER JOIN programs as pg ON i.programid = pg.[ID]
                  WHERE i.[time] BETWEEN ... //SOME MORE CODE IS FOLLOWING HERE!
                    ";

我知道使用“exists”关键字很难,但有没有“单行”解决方案?我发现了几个额外的案例选择解决方案。由于我在多个不同列的地方需要此解决方案,因此案例选择解决方案不适合。 感谢您的帮助

【问题讨论】:

您使用的是哪个 rdbms?例如 sql-server、mysql 还是其他? 对不起,是sql-server。 exists,你的意思是不是null 有点跑题了;在生产查询中使用nolock 可以是very dangerous。 NoLock 可能会丢失行、返回重复项并包含未提交的记录。 该列:timeTo 实际上存在于数据库中。 【参考方案1】:

SQL Server 不允许您引用不存在的字段。我怀疑这是因为查询优化器无法生成包含不存在字段的执行计划。

您的应用需要:

    确定正在使用的数据库版本。 选择适当的查询。 确保它处理丢失的数据(通过关闭依赖于新字段的功能或选择适当的默认值)。

【讨论】:

【参考方案2】:

您可以执行 if 语句并查询系统表。您需要在动态 sql 中执行此操作才能对其进行解析。

declare @sql nvarchar(max);

if exists (
    select 1 from sys.columns c
    inner join sys.tables t on c.object_id = t.object_id
    where c.name = 'timeTo' and t.name = 'inspection')
begin
    set @sql = 'SELECT i.[ID] AS cID, 
        pg.[Name], 
        pg.[ID] AS pgid, 
        i.[time],
        defect = CASE i.[defect] WHEN 0 THEN ''OK'' WHEN 1 THEN ''NOK'' END,                      
        timeTo = CASE i.[timeTo] WHEN EXISTS THEN i.[timeTo] ELSE NULL END                     
    FROM inspection AS i WITH (NOLOCK) INNER JOIN programs as pg ON i.programid = pg.[ID]
    WHERE i.[time] BETWEEN ... //SOME MORE CODE IS FOLLOWING HERE!';
end
else 
begin
    set @sql = 'SELECT i.[ID] AS cID, 
        pg.[Name], 
        pg.[ID] AS pgid, 
        i.[time],
        defect = CASE i.[defect] WHEN 0 THEN ''OK'' WHEN 1 THEN ''NOK'' END,                                           
    FROM inspection AS i WITH (NOLOCK) INNER JOIN programs as pg ON i.programid = pg.[ID]
    WHERE i.[time] BETWEEN ... ///SOME MORE CODE IS FOLLOWING HERE!';
end
exec (@sql);

【讨论】:

好的,谢谢!我现在已经做了类似的事情 - 但我希望/寻找一种更优雅的方式(单行代码解决方案)。

以上是关于SQL - 如果 OLEQuery 中存在,则选择列的主要内容,如果未能解决你的问题,请参考以下文章

SQL:单个人存在多个地址。如果存在则选择当前地址,否则选择永久地址

SQL Server存储过程选择,存在,多表

SQL 选择不同的行,如果为空则忽略行

HSQLDB 如果不存在则插入,如果存在则更新

SQL 查询 - 如果存在则更新,否则插入

比较两个表,如果存在则显示另一个表的值,如果不存在,则在 SQL 中显示状态