SQL 中的 LIKE 与整数

发布于 2024-11-03 00:40:03 字数 446 浏览 3 评论 0原文

我可以用整数 LIKE 语句替换 = 语句吗?

例如:以下是同一件事:

select * from FOOS where FOOID like 2    
// and 
select * from FOOS where FOOID = 2

我更喜欢使用 LIKE 而不是 = 因为当我没有 FOOID 过滤器时我可以使用 % ...

SQL Server 2005。

编辑1 @Martin
在此处输入图像描述

Can I replace the = statement with the LIKE one for the integers ?

by eg. are the following the same thing:

select * from FOOS where FOOID like 2    
// and 
select * from FOOS where FOOID = 2

I'd prefer to use LIKE instead of = because I could use % when I have no filter for FOOID...

SQL Server 2005.

EDIT 1 @Martin
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

治碍 2024-11-10 00:40:03
select * from FOOS where FOOID like 2

应避免,因为它会导致双方隐式转换为 varchar 并意味着索引无法用于满足查询。

CREATE  TABLE #FOOS
(
FOOID INT PRIMARY KEY,
Filler CHAR(1000)
)
INSERT INTO #FOOS(FOOID)
SELECT DISTINCT number 
FROM master..spt_values


SELECT * FROM #FOOS WHERE FOOID LIKE 2

SELECT * FROM #FOOS WHERE FOOID = 2

DROP TABLE #FOOS

计划(注意估计成本)

在此处输入图像描述

查看成本差异的另一种方法是添加 SET STATISTICS IO ON

您会看到第一个版本返回类似的内容

Table '#FOOS__000000000015'. Scan count 1, logical reads 310

第二个版本返回

Table '#FOOS__000000000015'. Scan count 0, logical reads 2

这是因为在此索引上查找所需的读取与索引深度成正比,而扫描所需的读取与数量成正比索引中的页面数。表格越大,这两个数字之间的差异就会越大。您可以通过运行以下命令来查看这两个数字。

SELECT index_depth, page_count
FROM
sys.dm_db_index_physical_stats (2,object_id('tempdb..#FOOS'), DEFAULT,DEFAULT, DEFAULT)
WHERE object_id = object_id('tempdb..#FOOS') /*In case it hasn't been created yet*/
select * from FOOS where FOOID like 2

should be avoided as it will cause both sides to be implicitly cast as varchar and mean that an index cannot be used to satisfy the query.

CREATE  TABLE #FOOS
(
FOOID INT PRIMARY KEY,
Filler CHAR(1000)
)
INSERT INTO #FOOS(FOOID)
SELECT DISTINCT number 
FROM master..spt_values


SELECT * FROM #FOOS WHERE FOOID LIKE 2

SELECT * FROM #FOOS WHERE FOOID = 2

DROP TABLE #FOOS

Plans (notice the estimated costs)

enter image description here

Another way of seeing the difference in costs is to add SET STATISTICS IO ON

You see that the first version returns something like

Table '#FOOS__000000000015'. Scan count 1, logical reads 310

The second version returns

Table '#FOOS__000000000015'. Scan count 0, logical reads 2

This is beacuse the reads required for the seek on this index are proportional to the index depth whereas the reads required for the scan are proportional to the number of pages in the index. The bigger the table gets the larger the discrepancy between these 2 numbers will become. You can see both of these figures by running the following.

SELECT index_depth, page_count
FROM
sys.dm_db_index_physical_stats (2,object_id('tempdb..#FOOS'), DEFAULT,DEFAULT, DEFAULT)
WHERE object_id = object_id('tempdb..#FOOS') /*In case it hasn't been created yet*/
月寒剑心 2024-11-10 00:40:03

使用 CASE 语句将输入字符串转换为整数。将通配符 % 转换为 NULL。与将整个 int 列隐式转换为字符串相比,这将提供更好的性能。

CREATE PROCEDURE GetFoos(@fooIdOrWildcard varchar(100))
AS
BEGIN
    DECLARE @fooId int

    SET @fooId =
        CASE
            -- Case 1 - Wildcard 
            WHEN @fooIdOrWildcard = '%'
                THEN NULL
            -- Case 2 - Integer
            WHEN LEN(@fooIdOrWildcard) BETWEEN 1 AND 9
            AND @fooIdOrWildcard NOT LIKE '%[^0-9]%'
                THEN CAST(@fooIdOrWildcard AS int)
            -- Case 3 - Invalid input
            ELSE 0
        END

    SELECT FooId, Name
    FROM dbo.Foos
    WHERE FooId BETWEEN COALESCE(@fooId, 1) AND COALESCE(@fooId, 2147483647)
END

Use a CASE statement to convert an input string to an integer. Convert the wildcard % to a NULL. This will give better performance than implicitly converting the entire int column to string.

CREATE PROCEDURE GetFoos(@fooIdOrWildcard varchar(100))
AS
BEGIN
    DECLARE @fooId int

    SET @fooId =
        CASE
            -- Case 1 - Wildcard 
            WHEN @fooIdOrWildcard = '%'
                THEN NULL
            -- Case 2 - Integer
            WHEN LEN(@fooIdOrWildcard) BETWEEN 1 AND 9
            AND @fooIdOrWildcard NOT LIKE '%[^0-9]%'
                THEN CAST(@fooIdOrWildcard AS int)
            -- Case 3 - Invalid input
            ELSE 0
        END

    SELECT FooId, Name
    FROM dbo.Foos
    WHERE FooId BETWEEN COALESCE(@fooId, 1) AND COALESCE(@fooId, 2147483647)
END
逆流 2024-11-10 00:40:03

是的,你可以直接使用它:

SELECT  *
FROM    FOOS
WHERE   FOOID like 2   

否则

SELECT  *
FROM    FOOS
WHERE   FOOID like '%'  

整数将被隐式转换为字符串。

请注意,这两个条件都不可控制,即无法在 fooid 上使用索引。这总是会导致全表扫描(或 fooid 上的全索引扫描)。

Yes, you can just use it:

SELECT  *
FROM    FOOS
WHERE   FOOID like 2   

or

SELECT  *
FROM    FOOS
WHERE   FOOID like '%'  

Integers will be implicitly converted into strings.

Note that neither of these condition is sargable, i. e. able to use an index on fooid. This will always result in a full table scan (or a full index scan on fooid).

我是男神闪亮亮 2024-11-10 00:40:03

这是一个迟来的评论,但我想也许其他人正在寻找同样的东西,所以当我能够找到解决方案时,我想我应该在这里分享:)

问题的简短描述:
我遇到的问题是能够使用通配符来对抗整数数据类型。我正在使用 SQL Server,因此我的语法适用于 SQL Server。我有一列显示部门编号,我想从下拉菜单中从我的页面传递一个变量。还有一个“全部”选项,在这种情况下我想传递“%”作为参数。我正在使用这个:

select * from table1 where deptNo Like @DepartmentID

当我传递一个数字时它起作用,但不适用于 % 因为 sql server 隐式地将 @DepartmentID 转换为 int (因为我的 deptNo 是 int 类型)

所以我转换了 deptNo 并解决了这个问题:

select * from table1 where CAST(deptNo AS varchar(2)) Like @DepartmentID

当我传递像 4 这样的数字和当我传递 % 时,这个都适用。

This is a late comment but I thought maybe some other people are looking for the same thing so as I was able to find a solution for this, I thought I should share it here:)

A short description of the problem:
the problem I had was to be able to use the wild card foe integer data types. I am using SQL Server and so my syntax is for SQL Server. I have a column which shows department number and I wanted to pass a variable from my page from a drop down menu. There is an 'All' option as well which in that case I wanted to pass '%' as the parameter. I was using this:

select * from table1 where deptNo Like @DepartmentID

It was working for when I pass a number but not for % because sql server implicitly converts the @DepartmentID to int (as my deptNo is of type int)

So I casted the deptNo and that fixed the issue:

select * from table1 where CAST(deptNo AS varchar(2)) Like @DepartmentID

This one works for both when I pass a number like 4 and when I pass %.

岁月打碎记忆 2024-11-10 00:40:03

使用 NULL 作为参数值而不是 % 作为通配符条件

select * from table1 where (@DepartmentID IS NULL OR deptNo = @DepartmentID)

Use NULL as the parameter value instead of % for your wildcard condition

select * from table1 where (@DepartmentID IS NULL OR deptNo = @DepartmentID)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文