为什么我会收到相同类型变量的“数据类型不匹配”错误?

问题描述 投票:0回答:2

在我的 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)
c# sqlite
2个回答
1
投票

调用

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();
}

0
投票

假设 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

(20) SQLITE_MISMATCH SQLITE_MISMATCH 错误代码表示 数据类型不匹配。

SQLite 通常非常宽容类型之间的不匹配 一个值以及该值所在容器的声明类型 被存储。例如,SQLite 允许应用程序存储 声明类型为 BOOLEAN 的列中的大 BLOB。但在几个 在这种情况下,SQLite 对类型非常严格。 SQLITE_MISMATCH错误是 当类型不匹配时,会在少数情况下返回。

表的rowid必须是整数。尝试将rowid设置为 除整数(或 NULL 之外的任何内容,它将自动 转换为下一个可用整数 rowid)会产生 SQLITE_MISMATCH 错误。

© www.soinside.com 2019 - 2024. All rights reserved.