【问题标题】:Compare a string database value with more than two words将字符串数据库值与两个以上的单词进行比较
【发布时间】:2015-08-24 11:34:31
【问题描述】:

我的数据库中有一个用户表,其中包含“全名”字段

在我的工具上,我正在上传一些文件,在将数据插入数据库之前,我通过比较数据库上的全名字段与文件上的全名字段来检查用户是否存在(这是唯一的选择,我无法比较 ID)。

我的问题是:当它们包含两个以上的单词时,如何比较这些字段?

有时全名不按顺序排列,例如:

-------------------------------------------------
|        Database       ||         File         |
-------------------------------------------------
| Michael Yves Pierrot  || Pierrot Michael Yves |
| Martin Dupont         || Dupont Martin        |
| Ben Jack Dupont       || Ben Dupont Jack      |
-------------------------------------------------

当只有两个词时,我可以使用这样的拆分:

public string getId()
{
    string result;
    QueryModel Query = new QueryModel();
    string sql = "SELECT Username_Id FROM USERNAME WHERE Full_name = '" 
        + Full_name.Replace("'", "''") + "'";
    result = Query.ExecuteCommand(sql, "int");
    if (result != "0")
    {
        string FullName2 = Full_name.Split(' ')[1] + " " + Full_name.Split(' ')[0];
        sql = "SELECT Username_Id FROM USERNAME WHERE Full_name = '" 
            + FullName2.Replace("'", "''") + "'";
        result = Query.ExecuteCommand(sql, "int");
    }
    return result;
}

注意Query.ExecuteCommand(sql, "int");在用户不存在时返回"0"

所以如果我的函数getId()返回"0"我将插入新用户,如果它返回别的东西,这意味着用户存在并将返回Username_Id

有人有想法吗?

谢谢。

【问题讨论】:

  • 也许使用 '%' 运算符?
  • 一个指示符是否相同可以是字符串的长度。

标签: c# sql-server asp.net-mvc database


【解决方案1】:

您可能会做如下不好的事情(因为潜在的性能成本而不好):

SELECT Username_Id 
FROM USERNAME 
WHERE Full_name LIKE '%Michael%' AND Full_name LIKE '%Pierrot%'

'%' 运算符用于通配符。 https://msdn.microsoft.com/en-us/library/ms189454.aspx

我也会参数化您的查询以防止 SQL 注入。

【讨论】:

  • 谢谢。就注射而言,我正在开发一个内部工具,我不必担心!
  • @aBennouna 参数化查询比仅仅防止 SQL 注入更有优势。它们还允许查询计划缓存,因此您的查询不必在每次执行时都进行编译。它的类型也更强,并且可以避免意外截断,因为您可以指定长度。因此,即使您的系统不易受到黑客攻击,出于准确性和性能原因,您也应该使用参数化查询。
【解决方案2】:

这将返回按字母顺序拆分和重新连接的所有部分。您可以从中创建一个函数并直接在您的比较中使用它

DECLARE @tbl TABLE(FullName VARCHAR(100));
INSERT INTO @tbl VALUES('Michael Yves Pierrot'),('Michael Pierrot Yves'),('Martin Dupon'),('Dupont Martin'),('Ben Jack Dupont'),('Ben Dupont Jack');

WITH
NamesSplitByXML AS
(
    SELECT FullName
          ,ROW_NUMBER() OVER(ORDER BY FullName) AS inx
          ,CAST('<root><r>' + REPLACE(tbl.FullName,' ','</r><r>') + '</r></root>' AS XML) AS NameAsXml
    FROM @tbl AS tbl
)
,SortedList AS
(
    SELECT inx, ROW_NUMBER() OVER(ORDER BY inx,x.y.value('.','varchar(max)')) AS inx2, FullName,x.y.value('.','varchar(max)') AS NamePart
    FROM NamesSplitByXML
    CROSS APPLY NameAsXml.nodes('/root/r') AS x(y)
) 
,DistinctInx AS
(
    SELECT DISTINCT inx,FullName FROM SortedList
)
SELECT DistinctInx.inx,FullName,ConcatAlphabetical.SortedName
FROM DistinctInx
CROSS APPLY
(
    SELECT STUFF(
    (
        SELECT TOP 100 PERCENT ' ' + NamePart
        FROM SortedList WHERE DistinctInx.inx=SortedList.inx
        ORDER BY inx2
        FOR XML PATH(''),TYPE
    ).value('.','varchar(max)'),1,1,'')
) AS ConcatAlphabetical(SortedName)

【讨论】:

  • @aBennouna,很抱歉问这个问题,因为已经有一个可以接受的答案,但是我花了很多时间在这上面(我喜欢棘手的 SQL hack!),我很好奇,如果你看看对此。它对你有用吗?
  • 对不起@Shnugo 我刚刚看到你的答案,我已经测试过了,它有效!谢谢;-)
  • @aBennouna,谢谢,很高兴听到这个消息......我的方法的一个优点是 - 如果您填写较小的部分,LIKE 搜索很容易返回错误的结果,其他名称可能包含这些部分也是。如果你坚持 LIKE 方式,你应该考虑添加空格:LIKE "% pierre %"。这确保找不到部分名称...
  • 我需要触发器方面的帮助,因为我知道您喜欢 SQL。可以帮我一把吗? @Shnugo
  • @aBennouna,当然可以!请在 SO 上提出一个新问题,用“sql-server”和“trigger”标记它,还有什么适合您的需求,您可以放心,帮助军队就像梅子蛋糕上的黄蜂一样。请使用问题下方的“分享”按钮获取链接。如果您在此处发布此内容(使用@Shnugo),我会收到警报并很快弹出:-)
【解决方案3】:

感谢@user1666620我修改了我的函数,新代码是:

public string getId()
{
    string result;
    QueryModel Query = new QueryModel();
    string[] fullName = Full_name.Replace("'", "''").Split(' ');
    string fullNameSQL = "";
    for (int i = 0; i < fullName.Count() - 1; i++)
    {
        string fn = "Full_Name LIKE '%" + fullName[i] + "%' ";
        fullNameSQL = (fullNameSQL == "") ? fn : fullNameSQL + " AND " + fn;
    }
    string sql = "SELECT Username_Id FROM USERNAME WHERE " + fullNameSQL;
    result = Query.ExecuteCommand(sql, "int");
    return result;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    相关资源
    最近更新 更多