c# SQLite参数化查询无法包含参数值



我试图重做一些SQLite查询,我在我的应用程序中使用参数而不是连接字符串,以确保我的代码不容易受到SQL注入攻击,并且在一般情况下更健壮。但是,我无法让任何参数化查询在我的应用程序中成功执行。我已经浏览了无数的例子和相关问题,但没有一个有帮助。

我的示例代码:
string connectionString = @"Datasource=C:UsersmesourcerepossamplebinDebugLogsLog.db3";
string commandText = "CREATE TABLE IF NOT EXISTS @tablename (Timestamp TEXT NOT NULL DEFAULT(STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), Loglevel TEXT, Callsite TEXT, Message TEXT);";
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
using (SQLiteCommand comm = conn.CreateCommand())
{
conn.Open();
comm.Parameters.AddWithValue("@tablename", "Service");
comm.CommandText = commandText;
int value = comm.ExecuteNonQuery();
}
}

当我在DBBrowser中为SQLite手动执行上述代码时,将'@tablename'替换为Service,就像我想以编程方式做的那样,查询工作正常,并插入表。

然而,当我执行代码时,我得到以下异常:

System.Data.SQLite.SQLiteException
HResult=0x800007BF
Message=SQL logic error
near "@tablename": syntax error
Source=System.Data.SQLite
StackTrace:
at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)
at System.Data.SQLite.SQLiteCommand.BuildNextCommand()
at System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)
at System.Data.SQLite.SQLiteDataReader.NextResult()
at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(CommandBehavior behavior)
at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
at SqliteParametersTest.Program.Main(String[] args) in C:UsersmesourcereposSqliteParametersTestSqliteParametersTestProgram.cs:line 23
This exception was originally thrown at this call stack:
System.Data.SQLite.SQLite3.Prepare(System.Data.SQLite.SQLiteConnection, string, System.Data.SQLite.SQLiteStatement, uint, ref string)
System.Data.SQLite.SQLiteCommand.BuildNextCommand()
System.Data.SQLite.SQLiteCommand.GetStatement(int)
System.Data.SQLite.SQLiteDataReader.NextResult()
System.Data.SQLite.SQLiteDataReader.SQLiteDataReader(System.Data.SQLite.SQLiteCommand, System.Data.CommandBehavior)
System.Data.SQLite.SQLiteCommand.ExecuteReader(System.Data.CommandBehavior)
System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(System.Data.CommandBehavior)
System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
SqliteParametersTest.Program.Main(string[]) in Program.cs

当我修改代码以省略参数名称前面的'@'字符时,代码执行成功,但是执行查询而不执行参数化它- IE尽管将参数名称从'@tablename'更改为'tablename',但执行的查询是:

CREATE TABLE IF NOT EXISTS

我有一种感觉,在这一点上,有一个更深层次的潜在问题,导致这可能与。net框架4.5版本,我选择了这个示例项目。使用的System.Data.Sqlite库版本为1.0.115.

在CREATE TABLE函数(或任何其他需要表名标识符的函数)的文档中都没有明确提到表名不能参数化:https://sqlite.org/lang_createtable.html.

无可否认,这个问题也归结于我没有正确设计我的SQLite数据库,从而导致我不得不使用不支持的功能,如:

在我的例子中,我意识到我在数据库中创建了3个结构几乎相同的不同表,最初的意图是我的每个服务将向每个表(与服务本身具有相同的名称)插入数据行,以便我可以在日志数据库中分离消息。

我相信纠正这个问题并确保我不必遇到这个问题,并且不会通过发送完全暴露的SQL查询的方式将我的代码暴露给SQL注入攻击的正确方法是:

  • 将相同的列名合并到一个表中
    • 将列'DateTime'和'Message'放在3个单独的表中,并使用单独的表名->1公共表,'DateTime'和'Message'列
  • 创建一个额外的列,标识我的3个服务中的哪一个在我的DB中创建了特定的行,这样我就可以实现能够识别每个单独的"消息"来自哪里的原始意图

最新更新