由于查询错误,Sqlite数据库返回不存在的列名而不是异常

g2ieeal7  于 2023-01-09  发布在  SQLite
关注(0)|答案(1)|浏览(139)

发现问题:

  • SqlKata编译器正在将列名转换为字符串文本,以便在找不到匹配列时返回。
  • 将查询更新为使用方括号而不是引号解决了该问题。
  • 在此创建了关于此问题的github问题:https://github.com/sqlkata/querybuilder/issues/655

初始帖子内容保留如下。
我正在对一个Sqlite数据库进行一些单元测试,以确保我的创建和读取方法都能正常工作(它们确实如此),但是其中一个测试失败了,我完全不知道为什么。
Sqlite db由单个表组成,定义如下:表名称:学生列:ID(主键)、名字(字符串)、姓氏(字符串)
以下查询工作正常,返回数据库中的"FirstName"值:

"SELECT \"FirstName\" FROM \"Students\" WHERE \"ID\" = @p0"

下面的查询可能会导致异常,因为列名不存在:

"SELECT \"UnknownCol\" FROM \"Students\" WHERE \"ID\" = @p0"

相反,我收到的值'UnknownCol'是字符串结果。
作为参考,我使用相同的方法(处理DbCommand对象)通过OledbCommand对Excel文件执行相同的操作。该函数产生了一个异常(不是一个有用的异常,但至少它错误我们的)。所以我知道底层方法是有效的。
为什么sqlite会返回查询中不存在的列的名称?
其他信息编辑:
当我在查询中请求无效列时,使用OledbConnection以相同的方法读取Excel工作表会导致以下异常(虽然它不会告诉您这是一个由于列名无效而导致的错误查询,但至少它会出错):

Exception Message: No value given for one or more required parameters.

完整代码链:

//db object has a method that returns a SqliteConnection, and has a 'Compiler' property that returns the SqlKata.Compiler object for SqlLite

var qry = new SqlKata.Query("Students").Select("UnknownCol").Where("ID",1);
return GetValue(db.GetConnection(), qry, db.Compiler);

//Results in the following sql: 
"SELECT \"UnknownCol\" FROM \"Students\" WHERE \"ID\" = 1"

---
public static object GetValue(DbConnection connection, Query query, SqlKata.Compilers.Compiler compiler)
{
    using (var cmd = connection.CreateCommand(query, compiler))
    {
        connection.Open();
        try
        {
            return cmd.ExecuteScalar();    
        }
        finally
        {
            connection.Close();
        }
    }
}

public static DbCommand CreateCommand(this DbConnection connection, SqlKata.Query query, SqlKata.Compilers.Compiler compiler)
{
    if (connection is null) throw new ArgumentNullException(nameof(connection));
    if (compiler is null) throw new ArgumentNullException(nameof(compiler));
    var result = compiler.Compile(query ?? throw new ArgumentNullException(nameof(query)));
    var cmd = connection.CreateCommand();
    cmd.CommandText = result.Sql;
    foreach (var p in result.NamedBindings)
    {
        _ = cmd.AddParameter(p.Key, p.Value);
    }
    return cmd;
}

public static DbParameter AddParameter(this DbCommand command, string name, object value)
{
    var par = command.CreateParameter();
    par.ParameterName = name;
    par.Value = value;
    command.Parameters.Add(par);
    return par;
}
ff29svar

ff29svar1#

在SQL中select字符串是法律的的。这是一个有效的SQL查询,它返回上述字符串:

SELECT 'UnknownCol';

它将返回包含此字符串literal的单行。

SELECT 'UnknownCol' FROM students;

对于表中的每一行,它都将返回一个包含此字符串literal的行。下面是一个测试数据库中包含几行的测试表的示例:

sqlite> select 'a string litteral' from test;
a string litteral
a string litteral
a string litteral
a string litteral
a string litteral
sqlite> select count(1) from test;
5
sqlite>

如果你想查询一个特定的列名,而不是字符串,你必须删除列名周围的''字符,那么这是一个未定义列的结果:

sqlite> select unknowncol from test;
Parse error: no such column: unknowncol
  select unknowncol from test;
         ^--- error here
sqlite>

或对于定义的列:

sqlite> select id from test;
1
2
3
4
6
sqlite>

相关问题