匹配用作撇号的左右单引号

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_nameperson_surnameperson_nickname等)并且将存在问题的字符在编辑点。这可以被有效地索引和搜索。与实施像 Lucene 这样的完整 NoSQL 解决方案相比,将这些数据存储在单独的 SQL 表/列中需要更少的应用程序重写。

上面的例子是一个简化:查询并没有像我上面解释的那样从字面上构建,我们确实实现了 SQL 注入(和其他)保护。

问题是如何将表数据中的斜撇号替换为直撇号。澄清:

  • 用户用品O‘Malley- 这应该匹配两者O‘MalleyO'Malley
  • 用户用品O'Malley- 这应该匹配两者O‘MalleyO'Malley

我们需要替换 SQL 数据,而不是用户的输入。我们可以在通过应用程序的过程中转换用户输入,这样如果他们输入有角度的撇号,我们在传递给 SQL 之前将它们更改为简单的撇号。这是我们需要标准化的 SQL 中的数据。

不幸的是,数据必须作为正确的尖括号保留在数据库中,但是当我们进行搜索时,我们需要将它们全部与直撇号进行匹配。

Ken*_*her 7

处理您的问题(并避免 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.