c# - 使用参数正确保护 SQL 语句

标签 c# sql sql-server

我的 C# 代码中有两个 SQL 语句来检索一些值。我知道它们对 SQL 注入(inject)是开放的,因为我没有使用参数,但我不确定我是否正确地实现了它们。

(注意:其中每一个都在循环中,循环遍历数据表的行) 第一个例子:

string sql2 = "select max(day) as day from users u join days d on d.User_ID = u.id where u.ActiveUser = 1 and u.id = " + Users["ID"].ToString();
command.CommandText = sql2;               
string dt = command.ExecuteScalar().ToString(); 

在上面的语句中,它检索日期时间并将其分配给字符串 dt。任何包含 id 或 ID 的内容都是 bigint。

string sql = "SELECT MAX(Day) FROM Days WHERE Project_ID IN (SELECT ID FROM Projects WHERE Parent_ID = -1 AND ID = " + row["ID"] +  ") HAVING MAX(Day) < DATEADD(dd, -730, getdate())";
command.CommandText = sql;                                  
object val = command.ExecuteScalar();

上面的语句与第一条语句相同,因为它正在检索日期时间值。任何带有 id 或 ID 的东西都是 bigint。

这是我第一次想到的,我是不是遗漏了什么或做错了什么?

string sql2 = "select max(day) as day from users u join days d on d.User_ID = u.id where u.ActiveUser = 1 and u.id = @userID";
using (conn)
{
     using (SqlCommand cmd = new SqlCommand(sql2, conn))
     {
          command.Parameters.AddWithValue("@userID", drUsers["ID"]);
          conn.Open();
          dt = (DateTime)command.ExecuteScalar();
     }
}

注意:上周我问了一个关于 DateTime 转换的问题,有一个问题无法解决,所以我可能不得不使用返回的日期时间的字符串版本。这会影响什么吗?

最佳答案

会是这样的:

string sql2 = @"select max(day) as day from users u 
join days d on d.User_ID = u.id 
where u.ActiveUser = 1 and u.id = @id";

string sql = @"SELECT MAX(Day) FROM Days 
WHERE Project_ID IN 
(SELECT ID FROM Projects WHERE Parent_ID = -1 AND ID = @id)
HAVING MAX(Day) < DATEADD(dd, -730, getdate())";

DateTime dt;
using (conn)
{
  using (SqlCommand cmd = new SqlCommand(sql2, conn))
  {
    cmd.Parameters.AddWithValue("@id", (Int64)Users["ID"]);
    conn.Open();
    dt = (DateTime)cmd.ExecuteScalar();
  }
}

using (conn)
{
  using (SqlCommand cmd = new SqlCommand(sql, conn))
  {
    cmd.Parameters.AddWithValue("@id", (Int64)row["ID"]);
    conn.Open();
    dt = (DateTime)cmd.ExecuteScalar();
  }
}

但是,出于性能原因,我不会在 DataTable 的每行中执行一次。您可以简单地将所有按 ID 分组的最大(天)值一次发送到客户端。即:

string sql = @"select u.Id, max(day) as day 
  from users u 
  join days d on d.User_ID = u.id 
  where u.ActiveUser = 1
  group by u.id";

编辑:我后来看到了您的编辑,以及有关日期时间的附加问题。不要将日期时间值转换为字符串。这是错误开始的地方。如果您“必须”,则仅使用不受 SQL 服务器设置影响的 ODBC 规范格式 - yyyyMMdd。其他类型的日期时间字符串只有偶然才能起作用。

关于c# - 使用参数正确保护 SQL 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34290028/

相关文章:

c# - 从 Word 文档转换为 HTML

c# - 使用反射检查属性是否仅为引用类型的 IEnumerable 而不是字符串或值类型

mysql - 使用 100 万行以上的表更新查询性能

java - ORA-00907 : Missing right parenthesis in SQL

SQL 使用 CMD 将数据从 .sql 文件插入到表中

c# - mvc3 从接口(interface)反射(reflect)具体类的数据注释

sql - 在调试 SQL 查询时需要帮助

sql - 当 JOIN 列在两个表中具有相同名称时,T-SQL 语法缩写?

SQL Server - 隐式连接与显式不同的结果

c# - 调用 httpClient.GetAsync() 时发送任何数据失败,有时会捕获 TaskCanceledException