使用参数正确保护SQL语句的安全
本文关键字:SQL 语句 安全 保护 确保 参数 | 更新日期: 2023-09-27 18:26:49
我的C#代码中有两条SQL语句来检索一些值。我知道它们对SQL注入是开放的,因为我没有使用参数,但我不确定我是否正确地实现了它们。
(注意:每一个都在循环中,循环通过数据表的行)第一个例子:
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分组的max(day)值一次性发送到客户端。即:
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";
编辑:我后来看到了你的编辑,还有关于日期时间的附加问题。不要将日期时间值转换为字符串。这就是错误的开始。如果"必须",则仅使用ODBC规范格式,该格式不受SQL server设置的影响-yyyyMMdd。其他类型的日期时间字符串只有在偶然的情况下才会起作用。
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";
DataTable tbl = new DataTable();
using (conn)
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
tbl.Load( cmd.ExecuteReader() );
conn.Close();
}
}
var dates = tbl.AsEnumerable()
.ToDictionary(t => t.Field<Int64>("ID"),
t => t.Field<DateTime?>("Day"));
然后在你的循环中,你可以这样说:
var myId = 4;
var myDate = dates[myId];