JLo*_*JLo 7 sql-server t-sql pattern-matching like
我有四列包含名称,并希望LIKE
在 Microsoft SQL Server 环境中使用 a 来搜索这些列。
复杂之处在于名称可能包括左右单引号/斜撇号(即‘
和’
,char(145)
和char(146)
),它们应该与直撇号匹配(即'
, char(39)
)
执行以下操作非常慢:
SELECT person_id
FROM person
WHERE REPLACE(
REPLACE(
person_name,
CHAR(145),
CHAR(39)
),
CHAR(146),
CHAR(39)
) LIKE '{USER_INPUT}'
Run Code Online (Sandbox Code Playgroud)
正如Stack Overflow 上的SQL 替换语句太慢中所解释的那样,这是因为使用REPLACE
使语句不可修改。
有没有办法让 SQL Server 以更好的方式处理这种情况?
已经提出的一种解决方案是具有应用程序产生一个“搜索”值,它串接所有字段(的person_name
,person_surname
,person_nickname
等)并且将存在问题的字符在编辑点。这可以被有效地索引和搜索。与实施像 Lucene 这样的完整 NoSQL 解决方案相比,将这些数据存储在单独的 SQL 表/列中需要更少的应用程序重写。
上面的例子是一个简化:查询并没有像我上面解释的那样从字面上构建,我们确实实现了 SQL 注入(和其他)保护。
问题是如何将表数据中的斜撇号替换为直撇号。澄清:
O‘Malley
- 这应该匹配两者O‘Malley
或O'Malley
O'Malley
- 这应该匹配两者O‘Malley
或O'Malley
我们需要替换 SQL 数据,而不是用户的输入。我们可以在通过应用程序的过程中转换用户输入,这样如果他们输入有角度的撇号,我们在传递给 SQL 之前将它们更改为简单的撇号。这是我们需要标准化的 SQL 中的数据。
不幸的是,数据必须作为正确的尖括号保留在数据库中,但是当我们进行搜索时,我们需要将它们全部与直撇号进行匹配。
处理您的问题(并避免 SQL 注入)的最佳方法是将您的用户输入作为变量传递。由于您使用的是 a ,因此LIKE
您可以执行以下操作:
CREATE TABLE #person (person_name nvarchar(50))
INSERT INTO #person VALUES (N'Bob'),(N'Bo''b'),(N'Bo‘b'),(N'Bo’b'),(N'Bo#b'),(N'Bo^b')
DECLARE @user_input nvarchar(50) = 'Bo’b'
SET @user_input = REPLACE(
REPLACE(
REPLACE(@user_input, N'‘', N''''),
N'’', N''''),
N'''', N'[‘’'']')
-- @user_input now == Bo[‘’']b
SELECT person_name
FROM #person
WHERE person_name LIKE @user_input
Run Code Online (Sandbox Code Playgroud)
基本上,这用单一类型(')替换了所有不同的 ',然后将 [] 放在所有三个周围,以便它们在LIKE
.