7

如何使用 SQLite 批量插入?

我查了一下,好像我用 select 语句做了一个插入。我搜索了一下,查看了示例,它们看起来都像是在将数据从一个表复制到另一个表,或者与 SQLite 不兼容。我想做类似的事情

"INSERT INTO user_msg_media (recipientId, mediaId, catagory, current_media_date) " +
"VALUES(@mediaId, @catagory, @current_media_date)";
where the value of recipientId is the watcher from each of
"SELECT watcher FROM userwatch WHERE watched=@watched";

我尝试了下面的代码,但收到错误“SQLite error no such column: watcher”

        command.CommandText =
            "CREATE TABLE if not exists user_msg_media( " +
            "msgId        INTEGER PRIMARY KEY, " +
            "recipientId  INTEGER, " +
            "mediaId      INTEGER, " +
            "catagory     INTEGER, " +
            "current_date DATE);";
        command.ExecuteNonQuery();

        //user media
        command.CommandText =
            "CREATE TABLE if not exists user_watch( " +
            "indx INTEGER PRIMARY KEY, " +
            "watcher INTEGER, " +
            "watched INTEGER);";
        command.ExecuteNonQuery();
        //...

    command.CommandText = "SELECT watcher FROM user_watch WHERE watched=:watched;";
    command.Parameters.Add(":watched", DbType.Int64).Value = 1;
    command.ExecuteNonQuery(); //is ok

    command.CommandText =
        "INSERT INTO user_msg_media (recipientId, mediaId, catagory, current_media_date) " +
        "SELECT watcher, :mediaId, :category, :current_media_date" +
        "FROM user_watch WHERE watched=:watched;";
    command.Parameters.Add(":mediaId", DbType.Int64).Value = 0;
    command.Parameters.Add(":category", DbType.Int64).Value = 0;
    command.Parameters.Add(":current_media_date", DbType.Int64).Value = 0;
    command.Parameters.Add(":watched", DbType.Int64).Value = 1;
    command.ExecuteNonQuery();
4

3 回答 3

7

我编写了一个类来帮助促进 SQLite 中的批量插入。希望它会有所帮助:

http://procbits.com/2009/09/08/sqlite-bulk-insert/

-J.P

于 2009-09-08T19:50:44.347 回答
2

SQlite 不支持@variable 表示法,但是(为了清楚起见,使用 sqlite 的 Python 绑定支持的命名占位符样式)这应该可以工作:

INSERT INTO user_msg_media (userId, mediaId, catagory, current_media_date)
SELECT watcher, :mediaId, :category, :current_media_date
FROM userwatch WHERE watched=:watched

编辑:SQLite 似乎误诊了哪个列名是错误的。列名全部固定后,以下 Python 代码对我有用(不确定您使用的是哪种其他语言,Python 是我与 sqlite 交互最方便的语言):

import sqlite3 as sq

con = sq.connect(':memory:')
cur = con.cursor()
cur.execute("CREATE TABLE if not exists user_msg_media( " +
            "msgId        INTEGER PRIMARY KEY, " +
            "recipientId  INTEGER, " +
            "mediaId      INTEGER, " +
            "catagory     INTEGER, " +
            "current_date DATE)")
cur.execute("CREATE TABLE if not exists user_watch( " +
            "indx INTEGER PRIMARY KEY, " +
            "watcher INTEGER, " +
            "watched INTEGER)")

cur.execute("INSERT INTO user_watch VALUES (1, 2, 3)")

cur.execute("SELECT watcher FROM user_watch WHERE watched=:watched",
            dict(watched=3))
print cur.fetchall()

print cur.execute("INSERT INTO user_msg_media (recipientId, mediaId, catagory, current_date) " +
        "SELECT watcher, :mediaId, :category, :current_media_date " +
        "FROM user_watch WHERE watched=:watched;",
        dict(mediaId=0, category=0, current_media_date=0, watched=3)
)

cur.execute("SELECT * FROM user_msg_media")
print cur.fetchall()

但是,如果我在您的 SQL 中重现不匹配,例如 current_date 与 current_media_date,我可以让它误诊为丢失的列是watcher,即使该列实际上很好。想尝试将这个更正后的代码放回您最喜欢的语言中,看看它的表现如何?

于 2009-05-30T03:01:34.243 回答
1

我建议使用来自 StackOverflow 的朋友的Dapper ORM 。如果您查看有关性能的部分,您不会比 Dapper 快多少。

多次执行命令
相同的签名还允许您方便有效地多次执行命令(例如批量加载数据)

示例用法:

connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
  ); // 3 rows inserted: "1,1", "2,2" and "3,3"

这适用于为某些 T 实现 IEnumerable 的任何参数。

于 2011-11-15T10:43:34.640 回答