Like 与“=” 使用 SQL Server 匹配字符串

发布于 2024-07-09 07:13:10 字数 798 浏览 7 评论 0原文

每当我编写一个基于字符串变量(varchar、nvarchar、char)选择数据的存储过程时,我都会有类似的内容:

procedure dbo.p_get_user_by_username(
    @username      nvarchar(256)
as
begin
    select
        u.username
        ,u.email
        --,etc
    from
        sampleUserTable u
    where
        u.username = @username
end

所以换句话说,为了匹配我想要的记录

u.username = @username

但有时我会遇到使用 < 的代码em>LIKE 代替 =

u.username like(@username)

您什么时候会使用它? 难道不应该只在需要一些通配符匹配时才使用它吗?

编辑

感谢您的回答。

我认为我需要澄清一下,我真正想问的是:是否可能存在一种情况,首选使用 like 代替“=”来进行精确的字符串匹配。 从答案来看我可以说不会。 根据我自己的经验,即使在我需要忽略大小写、前导和结尾空格的情况下,我也会在两个字符串上使用 ltrim、rtrim、lower,然后使用“=”。 再次感谢您的输入。

Whenever I write a stored procedure for selecting data based on string variable (varchar, nvarchar, char) I would have something like:

procedure dbo.p_get_user_by_username(
    @username      nvarchar(256)
as
begin
    select
        u.username
        ,u.email
        --,etc
    from
        sampleUserTable u
    where
        u.username = @username
end

So in other words to match the record I would have

u.username = @username

But sometimes I come across code that would use LIKE in place of =

u.username like(@username)

When would you use it?
Shouldn't that be used only when you need some wildcard matching?

EDIT

Thanks for the answers.

I think that I need to clarify that what I was really trying to ask was: if there could be a situation when it was preferred to use like in place of "=" for exact string matching. From the answers I could say that there would not be.
From my own experience even in situations when I need to ignore e.g case, and leading and ending spaces i would use ltrim, rtrim, lower on both strings and then "=". Thanks again for your input.

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

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

发布评论

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

评论(9

帥小哥 2024-07-16 07:13:10

你是对的。 除非您正在进行通配符匹配,否则使用 LIKE 没有任何好处。 此外,在没有通配符的情况下使用它可能会导致使用低效的查询计划。

You are correct. There is no benefit in using LIKE unless you are doing wild card matching. In addition, using it without wildcard could lead to the use of an inefficient queryplan.

淑女气质 2024-07-16 07:13:10

Sunny 几乎做对了:)

在 SQL2005 的默认安装中在 QA 中运行以下命令

select * from sysobjects where name = 'sysbinobjs   '
-- returns 1 row
select * from sysobjects where name like 'sysbinobjs   '
-- returns 0 rows

因此,LIKE 与尾随空格不匹配,在查询计划方面两者的性能几乎相同,但“=”连接的性能稍好一些。

使用 LIKE 时必须记住的另一件事是正确转义字符串。

declare @s varchar(40) 
set @s = 'escaped[_]_%'

select 1 where 'escaped[_]_%'  like @s 
--Return nothing = BAD 

set @s = '_e_s_c_a_p_e_d_[___]___%' 

select 1 where 'escaped[_]_%'  like @s escape '_'
--Returns 1 = GOOD

一般来说,人们不会使用LIKE来进行精确匹配,因为转义问题会导致各种复杂性和微妙的错误,人们会忘记转义,这是一个痛苦的世界。

但是……如果你想要真正高效的精确匹配,LIKE 可以解决问题。

假设您想要将用户名与“sam”匹配,并且不想得到“Sam”或“Sam”,不幸的是列的排序规则不区分大小写。

像下面这样的东西(添加了转义)是可行的方法。

select * from sysobjects
WHERE name = 'sysbinobjs' and name COLLATE Latin1_General_BIN LIKE 'sysbinobjs'

进行双重匹配的原因是为了避免表扫描。

然而....

我认为varbinary 转换技巧 不太容易出现错误并且更容易记住。

Sunny almost got it right :)

Run the following in QA in a default install of SQL2005

select * from sysobjects where name = 'sysbinobjs   '
-- returns 1 row
select * from sysobjects where name like 'sysbinobjs   '
-- returns 0 rows

So, LIKE does not match on trailing spaces, on the query plan side both perform almost equally, but the '=' join performs a tiny bit better.

An additional thing you MUST keep in mind when using LIKE is to escape your string properly.

declare @s varchar(40) 
set @s = 'escaped[_]_%'

select 1 where 'escaped[_]_%'  like @s 
--Return nothing = BAD 

set @s = '_e_s_c_a_p_e_d_[___]___%' 

select 1 where 'escaped[_]_%'  like @s escape '_'
--Returns 1 = GOOD

In general people do not use LIKE for exact matching, because the escaping issues cause all sorts of complications and subtle bugs, people forget to escape and there is a world of pain.

But ... if you want a real exact match that is efficient, LIKE can solve the problem.

Say, you want to match username to "sam" and do not want to get "Sam" or "Sam " and unfortunately the collation of the column is case insensitive.

Something like the following (with the escaping added) is the way to go.

select * from sysobjects
WHERE name = 'sysbinobjs' and name COLLATE Latin1_General_BIN LIKE 'sysbinobjs'

The reason you do a double match is to avoid a table scan.

However ....

I think the varbinary casting trick is less prone to bugs and easier to remember.

薔薇婲 2024-07-16 07:13:10

如果不使用通配符,则不同之处在于,“=”进行精确匹配,但 LIKE 将匹配带有尾随空格的字符串(来自 SSBO):

当您执行字符串比较时
使用 LIKE,所有字符
模式字符串很重要,
包括前导或尾随空格。
如果查询中的比较是
返回带有字符串 LIKE 的所有行
'abc'(abc 后跟一个
空格),其中的值的行
该列是 abc (abc 没有
空格)不被返回。 然而,
表达式 to 中的尾随空格
与模式匹配的是
被忽略。 如果查询中的比较是
返回带有字符串的所有行
LIKE 'abc'(不带空格的 abc),全部
以 abc 开头且为零的行
或返回更多尾随空白。

If no wildcards are used, then the difference is, that "=" makes an exact match, but LIKE will match a string with trailing spaces (from SSBO):

When you perform string comparisons
with LIKE, all characters in the
pattern string are significant,
including leading or trailing spaces.
If a comparison in a query is to
return all rows with a string LIKE
'abc ' (abc followed by a single
space), a row in which the value of
that column is abc (abc without a
space) is not returned. However,
trailing blanks, in the expression to
which the pattern is matched, are
ignored. If a comparison in a query is
to return all rows with the string
LIKE 'abc' (abc without a space), all
rows that start with abc and have zero
or more trailing blanks are returned.

飘落散花 2024-07-16 07:13:10

使用 LIKE 关键字,您可以匹配字段 u。 username 针对指定的模式而不是固定的“字符串”。

With the LIKE keyword you can match the field u.username against a specified pattern instead of a fixed "string".

只是偏爱你 2024-07-16 07:13:10

如果您在其他人的代码中看到这一点,也许他们打算允许一个人传递包含模式或通配符的字符串。

If you're seeing this in other people's code maybe they intended to allow a person to pass in a string that included a pattern or wildcards.

无语# 2024-07-16 07:13:10

是的 - 你是对的 - 它应该只用于通配符匹配。 应谨慎使用它,尤其是在非索引字段的非常大的表上,因为它会大大减慢您的查询速度。

Yes - you are right - it should only be used for wildcard matching. It should be used sparingly especially on very large tables on non-indexed fields as it can slow your queries WAY WAY down.

荆棘i 2024-07-16 07:13:10

我遇到了同样的问题。 使用 = 运行类似的查询大约需要一分半钟。 当我将 = 更改为 like 时,查询速度要快得多。

  • 尝试为您要比较的列创建索引。 这显着加快了查询速度。
  • 尝试运行 sp_updatestats。 就我而言,这使得使用不带索引的 = 查询在大约 6 秒内运行,而使用索引几乎立即运行。

I ran into the same problem. It took about a minute and a half to run similar query with =. When I changed = to like the query was much faster.

  • Try creating an index for the column you are comparing with. This sped up the query significantly.
  • Try running sp_updatestats. In my case this made the query run in about 6 seconds using = with out the index and almost instantly with the index.
趁年轻赶紧闹 2024-07-16 07:13:10

LIKE 用于通配符匹配,其中 as =(等于)用于精确匹配。

我还认为它用于已由全文目录编目的字段进行硬核字符串比较。

LIKE is for wildcard matching, where as = (equals) is for an exact matches.

I also think it used for fields that have been catalogued by FULL TEXT CATALOGUES for hard core string comparisons.

一梦浮鱼 2024-07-16 07:13:10

是的,据我所知,使用不带任何通配符的 like 与使用 = 运算符相同。 您确定输入参数中没有通配符吗?

Yes, as far as I know, using like without any wildcards is the same as using the = operator. are you sure the input parameter doesn't have wildcards in it?

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