在我的 SQLite 数据库中,有一个表和一个链接到该表的虚拟表,我收到一个错误,表明表和/或变量具有不同的类型。我检查了我的打字,没有发现任何错误。
using Microsoft.Data.Sqlite;
namespace SqliteExample
{
struct Track
{
public string FilePath;
public string Artist;
public string Title;
public Track(string file_path, string artist, string title)
{
FilePath = file_path;
Artist = artist;
Title = title;
}
}
class Program
{
static async Task Main(string[] args)
{
// Get database connection
var connection = await Init();
await InsertTracks(connection, [new Track("test_path", "test_artist", "test_title")]);
}
static async Task<SqliteConnection> Init()
{
// Make a connection to our database and open it
var connection = new SqliteConnection("Data Source=meta.db");
await connection.OpenAsync();
// Create tables if they don't already exist
using (var command = connection.CreateCommand())
{
Console.WriteLine("\nCreating tables...");
// Create metadata table
command.CommandText = """
CREATE TABLE IF NOT EXISTS meta (
file TEXT PRIMARY KEY,
artist TEXT,
title TEXT
)
""";
await command.ExecuteNonQueryAsync();
// Create FTS5 virtual table
command.CommandText = """
CREATE VIRTUAL TABLE IF NOT EXISTS search USING fts5(
artist,
title,
content='meta',
content_rowid='file'
);
""";
await command.ExecuteNonQueryAsync();
// Push triggers
command.CommandText = """
CREATE TRIGGER IF NOT EXISTS insert_search AFTER INSERT ON meta BEGIN
INSERT INTO search(rowid, artist, title) VALUES (new.file, new.artist, new.title);
END;
CREATE TRIGGER IF NOT EXISTS update_search AFTER UPDATE ON meta BEGIN
INSERT INTO search(search, rowid, artist, title) VALUES ('delete', old.file, old.artist, old.title);
INSERT INTO search(rowid, artist, title) VALUES (new.file, new.artist, new.title);
END;
CREATE TRIGGER IF NOT EXISTS delete_search AFTER DELETE ON meta BEGIN
INSERT INTO search(search, rowid, artist, title) VALUES ('delete', old.file, old.artist, old.title);
END;
""";
await command.ExecuteNonQueryAsync();
}
return connection;
}
static async Task InsertTracks(SqliteConnection connection, Track[] tracks)
{
using (var command = connection.CreateCommand())
{
Console.WriteLine("\nInserting entries...");
command.CommandText = "INSERT INTO meta (file, artist, title) VALUES ($path, $artist, $title)";
foreach (Track track in tracks)
{
command.Parameters.Add("$path", SqliteType.Text).Value = track.FilePath;
command.Parameters.Add("$artist", SqliteType.Text).Value = track.Artist;
command.Parameters.Add("$title", SqliteType.Text).Value = track.Title;
await command.ExecuteNonQueryAsync();
}
}
}
}
}
完整错误消息:
Unhandled exception. Microsoft.Data.Sqlite.SqliteException (0x8000
4005): SQLite Error 20: 'datatype mismatch'.
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(In
t32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBeh
avior behavior)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader()
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteNonQuery()
at System.Data.Common.DbCommand.ExecuteNonQueryAsync(Cancellati
onToken cancellationToken)
--- End of stack trace from previous location ---
at SqliteExample.Program.InsertTracks(SqliteConnection connecti
on, Track[] tracks) in E:\Documents\projects\sqlite-in-csharp\Sqli
teExample\Program.cs:line 201
at SqliteExample.Program.Main(String[] args) in E:\Documents\pr
ojects\sqlite-in-csharp\SqliteExample\Program.cs:line 39
at SqliteExample.Program.<Main>(String[] args)
调用
InsertTracks
时,请确保正确传递数组:
await InsertTracks(connection, new Track[] { new Track("test_path", "test_artist", "test_title") });
在查询字符串中添加参数时,您会添加具有不同值的相同参数,这会导致错误。确保您在循环之外执行此操作。稍后您可以在循环内赋值。
var pathParam = command.Parameters.Add("$path", SqliteType.Text);
var artistParam = command.Parameters.Add("$artist", SqliteType.Text);
var titleParam = command.Parameters.Add("$title", SqliteType.Text);
// Now iterate over the tracks and assign values
foreach (Track track in tracks)
{
pathParam.Value = track.FilePath;
artistParam.Value = track.Artist;
titleParam.Value = track.Title;
await command.ExecuteNonQueryAsync();
}
假设 rowid 列不是名为
rowid
的用户定义列(错误表明它不是),则 rowid
,必须是整数值,这是数据类型不匹配的唯一原因错误。
new.file
/old.file
可能不是一个整数值(如果您相信它是那么尝试CAST(new.file AS INTEGER
)和old.file
。
另一种方法是将 roiwd 设置为 null,或者不指定 rowid 列;无论哪种情况,都会生成该值,并且通常比现有的最高 rowid 大 1 (不能保证单调递增的 rowid 值,请参阅链接数据不匹配中的
rowid
链接,了解有关 rowid
的更多信息)专栏)
INSERT
使用默认的CONFLICT
处理,即ABORT(也许可以考虑使用INSERT OR IGNORE
)只会跳过一个独特的冲突,这显然取决于您想要的功能).但是,您可能(应该)确实希望将
file
存储在content_rowid
列中,在这种情况下,您应该分配而不是将INSERT
中的值分配给rowid
/在 SQL 中使用 content_rowid
。
content_rowid
栏)。(20) SQLITE_MISMATCH SQLITE_MISMATCH 错误代码表示 数据类型不匹配。
SQLite 通常非常宽容类型之间的不匹配 一个值以及该值所在容器的声明类型 被存储。例如,SQLite 允许应用程序存储 声明类型为 BOOLEAN 的列中的大 BLOB。但在几个 在这种情况下,SQLite 对类型非常严格。 SQLITE_MISMATCH错误是 当类型不匹配时,会在少数情况下返回。
表的rowid必须是整数。尝试将rowid设置为 除整数(或 NULL 之外的任何内容,它将自动 转换为下一个可用整数 rowid)会产生 SQLITE_MISMATCH 错误。