2009-03-09 21 views

Respuesta

7

Debe usar la interfaz de instrucciones preparadas de sqlite. Básicamente, la idea es que se prepare una declaración con un marcador de posición para su representación de nota, a continuación, utiliza una de las unen llama a "atar" sus datos ...

SQLite Prepared Statements

+0

He estado buscando un equivalente INSERT de 'GetBytes 'pero parece que ni el proveedor de phxsoftware ni devart.com tienen una forma de insertar datos sin tener primero todo el archivo en la memoria (el' SQLiteBlob' de devart.com parecía prometedor, pero no parece ser compatible). –

73

Así es como se puede hacer en C# :

class Program 
{ 
    static void Main(string[] args) 
    { 
     if (File.Exists("test.db3")) 
     { 
      File.Delete("test.db3"); 
     } 
     using (var connection = new SQLiteConnection("Data Source=test.db3;Version=3")) 
     using (var command = new SQLiteCommand("CREATE TABLE PHOTOS(ID INTEGER PRIMARY KEY AUTOINCREMENT, PHOTO BLOB)", connection)) 
     { 
      connection.Open(); 
      command.ExecuteNonQuery(); 

      byte[] photo = new byte[] { 1, 2, 3, 4, 5 }; 

      command.CommandText = "INSERT INTO PHOTOS (PHOTO) VALUES (@photo)"; 
      command.Parameters.Add("@photo", DbType.Binary, 20).Value = photo; 
      command.ExecuteNonQuery(); 

      command.CommandText = "SELECT PHOTO FROM PHOTOS WHERE ID = 1"; 
      using (var reader = command.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        byte[] buffer = GetBytes(reader); 
       } 
      } 

     } 
    } 

    static byte[] GetBytes(SQLiteDataReader reader) 
    { 
     const int CHUNK_SIZE = 2 * 1024; 
     byte[] buffer = new byte[CHUNK_SIZE]; 
     long bytesRead; 
     long fieldOffset = 0; 
     using (MemoryStream stream = new MemoryStream()) 
     { 
      while ((bytesRead = reader.GetBytes(0, fieldOffset, buffer, 0, buffer.Length)) > 0) 
      { 
       stream.Write(buffer, 0, (int)bytesRead); 
       fieldOffset += bytesRead; 
      } 
      return stream.ToArray(); 
     } 
    } 
} 
+1

¡Gracias! : D (marca como aceptado por la mañana después de intentar el código de prueba) –

+0

¿Cómo se usa esto en C#? Cogí http://www.codeproject.com/KB/database/cs_sqlitewrapper.aspx y agregué la fuente a mi clase y usé el espacio de nombres. Pero pareces usar http://sqlite.phxsoftware.com/, así que intenté instalar eso pero no tuve suerte (designer/install.exe). También miré en el archivo .chm –

+4

Descargué System.Data.SQLite.dll desde http://sqlite.phxsoftware.com/ y lo agregué a las referencias del proyecto. No hay necesidad de instalar nada. –

6

terminé con este método para insertar una mancha:

protected Boolean updateByteArrayInTable(String table, String value, byte[] byteArray, String expr) 
    { 
     try 
     { 
     SQLiteCommand mycommand = new SQLiteCommand(connection); 
     mycommand.CommandText = "update " + table + " set " + value + "[email protected]" + " where " + expr; 
     SQLiteParameter parameter = new SQLiteParameter("@image", System.Data.DbType.Binary); 
     parameter.Value = byteArray; 
     mycommand.Parameters.Add(parameter); 

     int rowsUpdated = mycommand.ExecuteNonQuery(); 
     return (rowsUpdated>0); 
     } 
     catch (Exception) 
     { 
     return false; 
     } 
    } 

para leer de nuevo el código es:

protected DataTable executeQuery(String command) 
    { 
     DataTable dt = new DataTable(); 
     try 
     { 
     SQLiteCommand mycommand = new SQLiteCommand(connection); 
     mycommand.CommandText = command; 
     SQLiteDataReader reader = mycommand.ExecuteReader(); 
     dt.Load(reader); 
     reader.Close(); 
     return dt; 
     } 
     catch (Exception) 
     { 
     return null; 
     } 
    } 

    protected DataTable getAllWhere(String table, String sort, String expr) 
    { 
     String cmd = "select * from " + table; 
     if (sort != null) 
     cmd += " order by " + sort; 
     if (expr != null) 
     cmd += " where " + expr; 
     DataTable dt = executeQuery(cmd); 
     return dt; 
    } 

    public DataRow getImage(long rowId) { 
     String where = KEY_ROWID_IMAGE + " = " + Convert.ToString(rowId); 
     DataTable dt = getAllWhere(DATABASE_TABLE_IMAGES, null, where); 
     DataRow dr = null; 
     if (dt.Rows.Count > 0) // should be just 1 row 
     dr = dt.Rows[0]; 
     return dr; 
    } 

    public byte[] getImage(DataRow dr) { 
     try 
     { 
     object image = dr[KEY_IMAGE]; 
     if (!Convert.IsDBNull(image)) 
      return (byte[])image; 
     else 
      return null; 
     } catch(Exception) { 
     return null; 
     } 
    } 

    DataRow dri = getImage(rowId); 
    byte[] image = getImage(dri); 
+1

+1 para el conjunto de bytes moldeado en 'getImage'. ¡Salvador de la vida! – DanM7

+0

en qué idioma se supone que debe estar? – user5359531

+0

java es lo que estaba usando en el momento – cdavidyoung

2

En C++ (sin comprobación de errores):

std::string blob = ...; // assume blob is in the string 


std::string query = "INSERT INTO foo (blob_column) VALUES (?);"; 

sqlite3_stmt *stmt; 
sqlite3_prepare_v2(db, query, query.size(), &stmt, nullptr); 
sqlite3_bind_blob(stmt, 1, blob.data(), blob.size(), 
        SQLITE_TRANSIENT); 

Eso puede ser SQLITE_STATICif the query will be executed before blob gets destructed.

4

Esto funcionó bien para mí (C#):

byte[] iconBytes = null; 
using (var dbConnection = new SQLiteConnection(DataSource)) 
{ 
    dbConnection.Open(); 
    using (var transaction = dbConnection.BeginTransaction()) 
    { 
     using (var command = new SQLiteCommand(dbConnection)) 
     { 
      command.CommandText = "SELECT icon FROM my_table"; 

      using (var reader = command.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        if (reader["icon"] != null && !Convert.IsDBNull(reader["icon"])) 
        { 
         iconBytes = (byte[]) reader["icon"]; 
        } 
       } 
      } 
     } 
     transaction.Commit(); 
    } 
} 

No hay necesidad de fragmentación. Simplemente lanzar a una matriz de bytes.

+0

¿en qué idioma se supone que debe estar? – user5359531

+1

C#. He agregado esto en el comentario. – breez

+0

Como alguien nuevo en SQLite, ¡esta respuesta es increíble! – JNW

0

Puesto que no hay ejemplo completo para C++, sin embargo, esto es cómo se puede insertar y recuperar una matriz/vector de los datos de flotador sin comprobación de errores:

#include <sqlite3.h> 

#include <iostream> 
#include <vector> 

int main() 
{ 
    // open sqlite3 database connection 
    sqlite3* db; 
    sqlite3_open("path/to/database.db", &db); 

    // insert blob 
    { 
     sqlite3_stmt* stmtInsert = nullptr; 
     sqlite3_prepare_v2(db, "INSERT INTO table_name (vector_blob) VALUES (?)", -1, &stmtInsert, nullptr); 

     std::vector<float> blobData(128); // your data 
     sqlite3_bind_blob(stmtInsertFace, 1, blobData.data(), static_cast<int>(blobData.size() * sizeof(float)), SQLITE_STATIC); 

     if (sqlite3_step(stmtInsert) == SQLITE_DONE) 
      std::cout << "Insert successful" << std::endl; 
     else 
      std::cout << "Insert failed" << std::endl; 

     sqlite3_finalize(stmtInsert); 
    } 

    // retrieve blob 
    { 
     sqlite3_stmt* stmtRetrieve = nullptr; 
     sqlite3_prepare_v2(db, "SELECT vector_blob FROM table_name WHERE id = ?", -1, &stmtRetrieve, nullptr); 

     int id = 1; // your id 
     sqlite3_bind_int(stmtRetrieve, 1, id); 

     std::vector<float> blobData; 
     if (sqlite3_step(stmtRetrieve) == SQLITE_ROW) 
     { 
      // retrieve blob data 
      const float* pdata = reinterpret_cast<const float*(sqlite3_column_blob(stmtRetrieve, 0)); 
      // query blob data size 
      blobData.resize(sqlite3_column_bytes(stmtRetrieve, 0)/static_cast<int>(sizeof(float))); 
      // copy to data vector 
      std::copy(pdata, pdata + static_cast<int>(blobData.size()), blobData.data()); 
     } 

     sqlite3_finalize(stmtRetrieve); 
    } 

    sqlite3_close(db); 

    return 0; 
} 
Cuestiones relacionadas