Как выполнить массовую вставку с помощью SQLite? - PullRequest
7 голосов
/ 30 мая 2009

Как выполнить массовую вставку с помощью 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: нет такого столбца: 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();

Ответы [ 3 ]

8 голосов
/ 08 сентября 2009

Я написал класс для облегчения массовых вставок в SQLite. Надеюсь, это полезно:

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

-JP

2 голосов
/ 30 мая 2009

SQlite не поддерживает нотацию @variable, но (для ясности используется стиль именованных заполнителей, поддерживаемый привязкой Python для sqlite):

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

Edit: 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, даже если этот столбец на самом деле в порядке. Хотите попробовать вернуть этот исправленный код на ваш любимый язык и посмотреть, как он себя ведет?

1 голос
/ 15 ноября 2011

Я бы предложил использовать Dapper ORM от наших друзей в StackOverflow. Если вы посмотрите на раздел о производительности, вы не сможете получить намного быстрее, чем 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"

Это работает для любого параметра, который реализует IEnumerable для некоторого T.

...