加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SELECT中的MSSQL强制转换([varcharColumn]为int)在WHERE子句过滤

发布时间:2020-12-12 16:21:46 所属栏目:MsSql教程 来源:网络整理
导读:假设以下架构和查询: 请查看我们希望在varchar列中包含值的明显设计问题. create table dbo.Parent ( Id bigint NOT NULL,TypeId int NOT NULL)create table dbo.Child ( Id bigint NOT NULL,ParentId bigint NOT NULL,TypeId int NOT NULL,varcharColumn va
假设以下架构和查询:

请查看我们希望在varchar列中包含值的明显设计问题.

create table dbo.Parent (
    Id bigint NOT NULL,TypeId int NOT NULL
)

create table dbo.Child (
    Id bigint NOT NULL,ParentId bigint NOT NULL,TypeId int NOT NULL,varcharColumn varchar(300) NULL
)

select cast(c.varcharColumn as int)
from dbo.Parent p (nolock)
    inner join dbo.Child c (nolock)
        on p.Id = c.ParentId
            and c.TypeId = 2
where p.TypeId = 13

休息时间:

由于无法转换为int的值,我们得到转换中断.在这种情况下:“123-1”.奇怪的是,正在转换的值会从最终结果集中过滤掉.

例如,这会返回零结果

select c.varcharColumn
from dbo.Parent p (nolock)
    inner join dbo.Child c (nolock)
        on p.Id = c.ParentId
            and c.TypeId = 2
where p.TypeId = 13
    and c.varcharColumn = '123-1'

查询计划最终查看Child表并实际在where子句之前应用cast函数.

我们能够通过在子表上创建一个新索引来解决这个问题(它正在进行PK扫描)

create index [NCIDX_dbo_Child__TypeId] on dbo.Child (
    TypeId
)
include (
    ParentId,varcharColumn
)

它现在首先过滤父表的where子句.

有没有办法解决这个没有额外的索引?同样,请不要提出任何与修复架构相关的建议.在这种情况下,这绝对是正确的解决方案.

我最感兴趣的是理解为什么它在过滤结果集之前应用了强制转换.

谢谢

编辑 – 答案:

非常感谢Aaron和Gordon.如果我获得超过15个代表点,我会回复你的两个回复.

我们最终需要Gordon的答案,因为我们想在视图中使用此查询.办公室的一些人对使用案例陈述持谨慎态度,因为他们更愿意控制以确保我们首先获得较小的结果集(Aaron的答案),但这一切都归结为查看查询计划并检查您的阅读计数.

再次感谢所有的回复!

解决方法

首先,这不是一个“明显的设计问题”. SQL是输出的描述性语言,而不是指定如何完成prcoessing的过程语言.通常,不保证处理顺序,这是一个优点.我可能会说存在设计问题,但它是围绕SQL语句中异常的一般处理.

根据SQL Server文档(http://msdn.microsoft.com/en-us/library/ms181765.aspx),您可以依赖于标量表达式的CASE语句的evauation顺序.所以,以下应该工作:

select (case when isnumeric(c.varcharColumn) = 1 then cast(c.varcharColumn as int) end)

或者,更接近“int”表达式:

select (case when isnumeric(c.varcharColumn) = 1 and c.varcharColumn not like '%.%' and c.varcharColumn not like '%e%'
             then cast(c.varcharColumn as int)
        end)

至少你的代码正在做一个明确的CAST.当演员表是隐含的(并且有数百列)时,这种情况会更加糟糕.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读