C# 可以在SQLite查询中参数化表名和列名吗?

C# 可以在SQLite查询中参数化表名和列名吗?,c#,sqlite,C#,Sqlite,我试图从C#在SQLite中执行参数化查询,我使用的方法是使用 SQLiteCommand cmd = new SQLiteCommand( "SELECT [ID]" + ",[email]" + ",[serializedata]" + ",[restrictions]" + " FROM " + UserTable + " WHERE @search =

我试图从C#在SQLite中执行参数化查询,我使用的方法是使用

        SQLiteCommand cmd = new SQLiteCommand(
        "SELECT [ID]" +
            ",[email]" +
            ",[serializedata]" +
            ",[restrictions]" +
        " FROM " + UserTable +
        " WHERE @search = @searchparam", SQLConnection);

        cmd.Parameters.Add(new SQLiteParameter("@searchparam"));
        cmd.Parameters.Add(new SQLiteParameter("@search"));
并这样称呼它:

        Command.Parameters["@searchparam"].Value = searchdata;
        Command.Parameters["@search"].Value = search;
        SQLiteDataAdapter slda = new SQLiteDataAdapter(UserSelectUsernameCommand);
        DataSet ds = new DataSet();
        slda.Fill(ds);
        User[] array = new User[ds.Tables[0].Rows.Count];
        int index = 0;
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            array[index] = new User(this, row);
            index++;
        }
        return array;
但是我在“@search”不是一个正确的列名”之类的行中得到了一个错误。如果我使用一个固定的列名,并且只使用参数的数据,那么它可以工作,但是我不想在需要按不同的列名搜索时创建10个不同的命令


这里的问题是什么?

通常,列名(或表名)之类的内容可以参数化,而且存在不同的索引这一事实意味着它必须在内部采用不同的计划。因此,您必须使用连接-,但要小心将已知列名列成白名单,以防止sql注入:

    SQLiteCommand cmd = new SQLiteCommand(@"
    SELECT [ID],[email],[serializedata],[restrictions]
    FROM " + whiteListedUserTable + @"
    WHERE [" + whiteListedColumnName + @"] = @searchparam", SQLConnection);

    cmd.Parameters.Add(new SQLiteParameter("@searchparam"));
    ...
    Command.Parameters["@searchparam"].Value = searchdata;

您不能以这种方式使用查询参数——指示列名。您只能使用它来提供值

请考虑以下内容:

    SQLiteCommand cmd = new SQLiteCommand(
    "SELECT [ID]" +
        ",[email]" +
        ",[serializedata]" +
        ",[restrictions]" +
    " FROM " + UserTable +
    " WHERE [" + search + "] = @searchparam", SQLConnection);

    cmd.Parameters.Add(new SQLiteParameter("@searchparam"));

如果您控制此函数的所有输入,而如果它可以由您以外的人提供,则没有输入,那么这应该是安全的。但是如果
search
来自不受信任的第三方,请确保对该值进行适当的安全检查。

如果您避免创建10个不同的命令,因为将每个命令绑定到SqliteConnection并反复建立其参数和CommandText的效率低下,我只是想让读者知道还有其他选择。SqliteCommand有一个新的SqliteCommand()的无参数构造函数;并且它的连接属性在运行时是可分配的。因此,您可以只创建和初始化一次多个命令,然后将它们的连接属性指定给在运行时重复创建和释放的SqliteConnection对象。