我想知道,如果一个字符串的最后一个字符是一个星号*
如何匹配TSQL中字符串的最后一个字符?
我有这给我的最后一个字符如下:
select RIGHT('hello*',1)
,但我会怎么使用它作为一个条件在if语句中通过匹配吗?以下不起作用,因为它只返回最后一个字符。
select '*' = RIGHT('hello*',1)
我可以使用正则表达式吗?
我想知道,如果一个字符串的最后一个字符是一个星号*
如何匹配TSQL中字符串的最后一个字符?
我有这给我的最后一个字符如下:
select RIGHT('hello*',1)
,但我会怎么使用它作为一个条件在if语句中通过匹配吗?以下不起作用,因为它只返回最后一个字符。
select '*' = RIGHT('hello*',1)
我可以使用正则表达式吗?
你只是在那里。通过使用:
select '*' = RIGHT('hello*',1)
的Sql评估RIGHT
但认为要别名它作为一个名为*
您可以使用条件表达式列:
if RIGHT('hello*',1) = '*'
print 'Ends in *'
else
print 'Does not end in *'
您可以过滤像等一张桌子:
select *
from MyTable
where RIGHT(MyColumn, 1) = '*';
虽然perfor mance将不会是恒星。 编辑:见卡尔Kieninger的答案如何,大大提高了该查询
的性能试试这个想法:
DECLARE @x NVARCHAR(32) = 'bbbbbbb*aaaaaaa';
IF(LEN(@x)=(SELECT LEN(@x) - CHARINDEX('*', REVERSE(@x)) + 1))
PRINT 'End with *'
ELSE
PRINT 'No end with *'
StuartLC提到的性能。您可以以索引持久计算列为代价来提高性能。这种战术已经在其他地方,如已经提到的几种:
我创建了一个样品,看看它在行动,但执行计划表明,它从来没有真正采摘提高我对索引期望的索引在计算列上的索引。所以现在我不确定我的测试有什么问题。如果有人能指出我的失败,我会更正答案。
CREATE TABLE Test(
TestData VARCHAR(10)
,TestData_Reverse AS REVERSE(TestData) PERSISTED
,TestData_Right1 AS RIGHT(TestData,1) PERSISTED
)
INSERT INTO Test(TestData) VALUES ('Bob'),('Joe'),('Ed*')
CREATE INDEX IX_Test_TestData ON Test (TestData)
CREATE INDEX IX_Test_TestData_Reverse ON Test (TestData_Reverse)
CREATE INDEX IX_Test_TestData_Right1 ON Test (TestData_Right1)
GO
SELECT * FROM Test WHERE TestData LIKE '%*' --Index Scan
SELECT * FROM Test WHERE RIGHT(TestData,1) = '*' --Table Scan
SELECT * FROM Test WHERE TestData LIKE '*%' --Index Seek
SELECT * FROM Test WHERE TestData_Reverse LIKE '*%' --Table Scan
SELECT * FROM Test WHERE LEFT(TestData_Reverse,1) = '*' --Index Scan
SELECT * FROM Test WHERE TestData_Right1 = '*' --Table Scan
DROP TABLE Test
编辑 - 临时编辑
这确实是优秀的 - 你只是需要更多的数据,从而使:
这里的更多的数据,测试在SQL Express 2014完成:
INSERT INTO Test(TestData)
SELECT o1.name + o2.name from sys.objects o1, sys.objects o2;
UPDATE STATISTICS Test;
SELECT TestData FROM Test WHERE TestData LIKE '%*' --Index Scan IX_Test_TestData *1 .038
SELECT TestData FROM Test WHERE RIGHT(TestData,1) = '*' --Index Seek (IX_Test_TestData_Right1) *2 .003
SELECT TestData FROM Test WHERE TestData LIKE '*%' --Index Seek IX_Test_TestData *3 .003
SELECT TestData FROM Test WHERE TestData_Reverse LIKE '*%' --Index Scan IX_Test_TestData *4 .038
SELECT TestData FROM Test WHERE LEFT(TestData_Reverse,1) = '*' --Index Scan IX_Test_TestData *5 .038
SELECT TestData FROM Test WHERE LEFT(TestData_Right1,1) = '*' --Index Scan IX_Test_TestData_Right1 *5 .031
SELECT TestData FROM Test WITH (INDEX = IX_Test_TestData_Reverse) WHERE TestData_Reverse LIKE '*%' --Index Scan IX_Test_TestData *6 .05
SELECT TestData FROM Test WHERE TestData_Right1 = '*' --Index Seek IX_Test_TestData_Right1 *7 .003
SELECT * FROM Test WHERE REVERSE(TestData) = '*dE' --Index Seek (IX_Test_TestData_Reverse) *8 .006
的好消息 IMO是SQL Server将能够 “神交” 这RIGHT(TestData,1)
可替代d为计算列并且使用IX_Test_TestData_Right1
(和REVERSE
* 8相同)。这意味着(对于非常具体的查询)(隐含地,对于非常具体的查询),持久计算的列可以隐藏在世界后面,像普通索引那样隐藏在幕后,并且意味着在有限的情况下实际上可以缓解函数缺乏可变性。
w.r.t.令人失望的扫描例如* 4,值得注意的是测试表是一个堆,并且Sql不使用LIKE运算符的可能原因之一是认为到集群的RID查找将超过使用IX_Test_TestData_Right/IX_Test_TestData_Reverse
TestData
。 我相信实际表格中的最佳策略是使用原始非反转列的INCLUDE
的覆盖索引。
CREATE INDEX IX_Test_TestData_Reverse ON Test (TestData_Reverse) INCLUDE (TestData)
SELECT TestData FROM Test WHERE TestData_Reverse LIKE '*%' --Index Scan IX_Test_TestData .003
这真是太好了,我不知道该SQL能够替代品具有同等功能持久化计算列(这意味着你也可以给优化搜索,非单调函数的错觉)。这个替换也发生在确定性标量('WITH SCHEMABINDING')用户定义的函数上。 – StuartLC
哦,对。 SQL Server刚刚决定使用蛮力的表太小,比尝试使用其他任何东西都快。我知道。感谢您的帮助。我很想离开临时编辑,但肯定会这样做,直到(除非)我有机会充分消化和整合。 –