通过字典生成类似于 WHERE 语句的字符串

发布于 2024-10-25 18:59:36 字数 1062 浏览 1 评论 0原文

我知道我们永远不应该这样做:

string select = "SELECT * FROM table1 ";
string where = "WHERE Name = '" + name + "' ";
string sql = select + where;
//execute the sql via ADO.NET

因为sql注入,因为name可以包含char ',因为另外100个原因。但现在我必须做一些类似的事情。我有一个 Dictionary ,其数据如下所示:

   Key(string)      Value(object)
    "Name"              "Bob"            //string
    "ID"              10092L             //long 
    "Birthday"      1980-05-07 00:00:00  //DateTime
    "Salary"          5000.5m            //decimal
//some others, whose key is a string, and value is string/long/int/DateTime/decimal

我想要一种简单的方法,将字典中的所有项目收集在 String 中,就像一个 where语句:

Name = 'Bob' and ID = 10092 and Birthday = '1980-05-07 00:00:00' and Salary = 5000.5

String和DateTime用'引用,但注意Name可以是O'Neal。有没有简单的实现方法?输入字典,返回结果字符串。

编辑 请注意,我想要的是字符串,我不会执行它,参数化命令没有帮助。我只想要一个看起来像完美安全的 WHERE 语句的字符串。

I know we should never do this:

string select = "SELECT * FROM table1 ";
string where = "WHERE Name = '" + name + "' ";
string sql = select + where;
//execute the sql via ADO.NET

because of sql injection, because name can contain the char ', because of another 100 reasons. But now I have to do something similiar. I have a Dictionary<string, object> whose data look like:

   Key(string)      Value(object)
    "Name"              "Bob"            //string
    "ID"              10092L             //long 
    "Birthday"      1980-05-07 00:00:00  //DateTime
    "Salary"          5000.5m            //decimal
//some others, whose key is a string, and value is string/long/int/DateTime/decimal

I want an easy way, to get all items in the dictionary collected in a String, just like a where statement:

Name = 'Bob' and ID = 10092 and Birthday = '1980-05-07 00:00:00' and Salary = 5000.5

String and DateTime are quoted with ', but note that the Name can be O'Neal. Is there any easy implementation? Input the dictionary, and return the string as a result.

EDIT Note that what I want is the string, I'm not going to execute it, parameterized command doesn't help. I just want a string that looks like a perfect safe WHERE statement.

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

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

发布评论

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

评论(5

何止钟意 2024-11-01 18:59:36

仅当 name 是用户输入的内容时,第一个代码才会出现问题。否则应该没问题。

我不知道它是否可以消除所有问题,但您可以尝试尝试类似 name = name.Replace("'", "''") 的方法。通过将所有单引号转换为双单引号,可以防止出现您所描述的问题类型。另一种方法可能是删除任何单引号。

然而,最好的途径是使用查询参数。 ADO 很好地支持这些,这也将消除任何注入攻击的可能性。

The first code is only a problem if name is something entered by the user. Otherwise, it should be fine.

I don't know that it eliminates all problems but you might try experimenting with something like name = name.Replace("'", "''"). By converting all single quotes to double single quotes, you prevent the type of problems you described. Another approach might be to remove any single quotes.

However, the best route is to use query arguments. ADO supports these nicely and that would also eliminate any possibility of injection attacks.

帝王念 2024-11-01 18:59:36

简单的方法可能是这样的:

string results = string.Join(" and ", myDict.Select( x=> x.Key + " = " +  x.Value)); 

这当然不会解决引号 ' 问题,具体取决于不同的数据类型,因此您不能将其用作 SQL 查询的输入 - 为此我强烈建议使用命名参数无论如何 - 但在其他方面是正确的,具体取决于字典中值的 ToString() 实现。

The easy way could be like this:

string results = string.Join(" and ", myDict.Select( x=> x.Key + " = " +  x.Value)); 

This of course wouldn't solve the quotes ' issue depending on different datatypes so you cannot use this as input to a SQL query - for that I would strongly recommend named parameters anyway - but is otherwise correct depending on the ToString() implementation of the values in your dictionary.

送君千里 2024-11-01 18:59:36

我很多年前写过这篇文章,并且一直使用它,再也不用考虑这个问题了。不止一次地解决这个问题是浪费脑细胞:

        //   replace things like:
    //         O'Keefe     with
    //          'O''Keefe'
    //   make sure you don't call this twice!
    static public string SqlString(string strInputSQL)
    {
        string strOut;
        strOut = strInputSQL;
        strOut = strOut.Replace ("'", "''");
        strOut = "'" + strOut + "'";
        return strOut;
    }

像这样使用:

string sql = "SELECT * FROM FOO WHERE Name LIKE " + SqlString(myvalue);

可能有十几种其他方法可以做到这一点,但如果您可以拥有一个且只有一个功能,并持续使用它,您将节省大量时间。

I wrote this many years ago, and always use it, and never ever have to think about this again. it is a waste of brain cells to solve this more than once:

        //   replace things like:
    //         O'Keefe     with
    //          'O''Keefe'
    //   make sure you don't call this twice!
    static public string SqlString(string strInputSQL)
    {
        string strOut;
        strOut = strInputSQL;
        strOut = strOut.Replace ("'", "''");
        strOut = "'" + strOut + "'";
        return strOut;
    }

Use it like this:

string sql = "SELECT * FROM FOO WHERE Name LIKE " + SqlString(myvalue);

There may be a dozen other ways to do it, but if you can have one and only one function, and use it consistently, you will save alot of time.

宛菡 2024-11-01 18:59:36

试试这个链接:将安全 SQL 语句创建为字符串

有些人认为这太过分了是经过精心设计的,或者只是打字很费力。不过,我还是依靠一个简单的论证...

有人已经投入了时间和精力,确保论证可以安全可靠地包含在 SQL 语句中。 是否 100% 确定您已经预先解决了所有可能的情况?或者经过测试的代码更有可能更可靠?

但是,我有点肛门;)

Try this link : Creating safe SQL statements as Strings

Some people consider this over-engineered, or just labourious to type. I fall back on a simple argument though...

Someone has already invested time and effort ensuring arguements can be safely and reliably included in SQL statements. Are you 100% certain you have pre-empted every possible scenario? Or is it more likely tried and tested code is more reliable?

But, then, I'm a bit anal ;)

救赎№ 2024-11-01 18:59:36
var sb = new StringBuilder();
var isFirst = true;
foreach (var element in dic)
{
    if(!isFirst)
        sb.Append(" AND ");
    else
        isFirst = false;
    sb.Append(element.Key);
    sb.Append(" = ");
    if(element.Value is decimal)
      sb.Append(CastToSqlDecimalString((decimal)element.Value));
    else
      sb.Append("'" + String.Format(CultureInfo.InvariantCulture, "{0:G}", element.Value).Replace("'", "''") + "'");
}

您可能想使用此函数处理小数

 public static string CastToSqlDecimalString(decimal dec)
        {
            var sqlDecimal = new System.Data.SqlTypes.SqlDecimal(dec);
            return string.Format("CAST({0} AS DECIMAL({1}, {2}))",
                        string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:G}", dec),
                        sqlDecimal.Precision,
                        sqlDecimal.Scale);
        }
var sb = new StringBuilder();
var isFirst = true;
foreach (var element in dic)
{
    if(!isFirst)
        sb.Append(" AND ");
    else
        isFirst = false;
    sb.Append(element.Key);
    sb.Append(" = ");
    if(element.Value is decimal)
      sb.Append(CastToSqlDecimalString((decimal)element.Value));
    else
      sb.Append("'" + String.Format(CultureInfo.InvariantCulture, "{0:G}", element.Value).Replace("'", "''") + "'");
}

You might want to handle decimals using this function

 public static string CastToSqlDecimalString(decimal dec)
        {
            var sqlDecimal = new System.Data.SqlTypes.SqlDecimal(dec);
            return string.Format("CAST({0} AS DECIMAL({1}, {2}))",
                        string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:G}", dec),
                        sqlDecimal.Precision,
                        sqlDecimal.Scale);
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文