Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
|
dbs:sqlite:start [2009/12/10 00:00] bebu angelegt |
dbs:sqlite:start [2022/09/22 19:58] (aktuell) |
||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| ====== SQLite ====== | ====== SQLite ====== | ||
| - | * FIXME Code steht erstmal hier, damit der Link nicht tot ist. | + | SQLite ist ein Datenbanksystem, das es ermöglicht eine Datenbank lokal auf dem Rechner zu erzeugen. Dazu legt sie ihre Daten in Form einer Datei auf der Festplatte ab. Man kann mit Hilfe von SQL Befehlen über die Konsole auf die Daten zugreifen oder aber eine der vielen Programmierschnittstellen benutzen, die für eine ganze Reihe von Programmiersprachen zur Verfügung stehen. Wer noch nie mit einem Datenbanksystem gearbeitet hat und für den SQL ein Fremdwort ist, der sollte [[dbs:sql:start|hier]] weitermachen, bevor er die folgenden Seiten liest. |
| - | * FIXME Code zerlegen, damit für C verwendbar; | + | |
| - | * FIXME Wrapperklasse als eigenen Unterpunkt; | + | |
| - | * FIXME Wrapperklasse im Tutorial langsam aufbauen? | + | |
| - | * FIXME Erläuterung an den neuen Namensraum und bereits früher erläuterte Informationen anpassen | + | |
| - | SQLite ist eine Bibliothek mit der man relationale Datenbanken mit Hilfe von SQL ((eng. Structured Query Language = "strukturierte Abfrage Sprache")) Befehlen verwalten kann. Es wird zwar nicht der gesamte SQL Standard unterstützt, das besondere im Vergleich zu anderen Systemen wie zum Beispiel MySQL ist jedoch, dass kein eigener Datenbankserver benötigt wird, sondern die gesamte Datenbank in einer einzelnen Datei gespeichert werden kann. Aus diesem Grund eignet sich SQLite vor allem für Fälle wo nicht mit extremen Datenmengen zu rechnen ist. Beliebt ist ihr Einsatz zum Beispiel auf den verschiedensten mobilen Geräten (Handy, PDA, ...) oder auch für normale Anwendungen. | + | * [[dbs:sqlite:why|Was spricht für SQLite]] |
| - | Beispielsweise verwendet Mozilla SQLite für Konfigurationswerte und seit Firefox 3 auch für Lesezeichen. Weiters wird es auch in Android oder im iPhoneOS verwendet. | + | * [[dbs:sqlite:libsqlite3:start|Einführung in die libsqlite3 Bibliothek für C/C++]] |
| - | + | ||
| - | ===== C++-Wrapper ===== | + | |
| - | + | ||
| - | FIXME Der Code sollte wohl noch etwas mehr erklärt werden...\\ | + | |
| - | Der Header: | + | |
| - | <code cpp> | + | |
| - | #include <string> | + | |
| - | #include <sqlite3.h> | + | |
| - | #include <stdexcept> | + | |
| - | #include <vector> | + | |
| - | #include <map> | + | |
| - | #include <iostream> | + | |
| - | + | ||
| - | class SQLite | + | |
| - | { | + | |
| - | public: | + | |
| - | + | ||
| - | typedef std::map<std::string,std::string> Row; | + | |
| - | typedef std::vector<Row> Result; | + | |
| - | + | ||
| - | //-------------------------------------------------------------------------- | + | |
| - | SQLite( const std::string& dbase) | + | |
| - | { | + | |
| - | checkCall( sqlite3_open(dbase.c_str(), &_db) ); | + | |
| - | } | + | |
| - | + | ||
| - | //-------------------------------------------------------------------------- | + | |
| - | ~SQLite() | + | |
| - | { | + | |
| - | sqlite3_close(_db); | + | |
| - | } | + | |
| - | + | ||
| - | //-------------------------------------------------------------------------- | + | |
| - | Result query( const std::string& query ) | + | |
| - | { | + | |
| - | //std::cout << query << std::endl; | + | |
| - | + | ||
| - | sqlite3_stmt *stmt; | + | |
| - | checkCall( sqlite3_prepare_v2(_db, query.c_str(), query.size(), &stmt, 0) ); | + | |
| - | + | ||
| - | int cols = sqlite3_column_count(stmt); | + | |
| - | Result result; | + | |
| - | + | ||
| - | while( sqlite3_step(stmt) == SQLITE_ROW ) | + | |
| - | { | + | |
| - | Row cur_row; | + | |
| - | + | ||
| - | for( int i = 0; i < cols; ++i ) | + | |
| - | { | + | |
| - | if( !sqlite3_column_name(stmt,i) ) | + | |
| - | continue; | + | |
| - | + | ||
| - | std::string name( sqlite3_column_name(stmt,i) ); | + | |
| - | if( name.empty() ) | + | |
| - | continue; | + | |
| - | + | ||
| - | std::string value; | + | |
| - | if( sqlite3_column_text(stmt,i) ) | + | |
| - | value = reinterpret_cast<const char*>(sqlite3_column_text(stmt,i)); | + | |
| - | + | ||
| - | cur_row[ name ] = value; | + | |
| - | } | + | |
| - | + | ||
| - | result.push_back(cur_row); | + | |
| - | } | + | |
| - | + | ||
| - | sqlite3_finalize(stmt); | + | |
| - | + | ||
| - | return result; | + | |
| - | } | + | |
| - | + | ||
| - | //-------------------------------------------------------------------------- | + | |
| - | void insert( const std::string& table, | + | |
| - | const Row& values ) | + | |
| - | { | + | |
| - | std::string col_names, col_values; | + | |
| - | + | ||
| - | for( Row::const_iterator col = values.begin(); | + | |
| - | col != values.end(); | + | |
| - | ++col ) | + | |
| - | { | + | |
| - | if( !col_names.empty() ) | + | |
| - | { | + | |
| - | col_names += ","; | + | |
| - | col_values += ","; | + | |
| - | } | + | |
| - | + | ||
| - | col_names += "`" + col->first + "`"; | + | |
| - | col_values += "'" + col->second + "'"; | + | |
| - | } | + | |
| - | + | ||
| - | query( "INSERT INTO " + table | + | |
| - | + " (" + col_names + ") VALUES (" + col_values + ")" ); | + | |
| - | } | + | |
| - | + | ||
| - | //-------------------------------------------------------------------------- | + | |
| - | Result select( const std::string& table, | + | |
| - | const Row& values ) | + | |
| - | { | + | |
| - | std::string checks; | + | |
| - | + | ||
| - | for( Row::const_iterator col = values.begin(); | + | |
| - | col != values.end(); | + | |
| - | ++col ) | + | |
| - | { | + | |
| - | if( !checks.empty() ) | + | |
| - | checks += " and "; | + | |
| - | + | ||
| - | checks += "`" + col->first + "`='" + col->second + "'"; | + | |
| - | } | + | |
| - | + | ||
| - | return query( "SELECT * FROM " + table + " WHERE " + checks ); | + | |
| - | } | + | |
| - | + | ||
| - | //-------------------------------------------------------------------------- | + | |
| - | void update( const std::string& table, | + | |
| - | const Row& values, | + | |
| - | const std::string& where ) | + | |
| - | { | + | |
| - | std::string sets; | + | |
| - | + | ||
| - | for( Row::const_iterator col = values.begin(); | + | |
| - | col != values.end(); | + | |
| - | ++col ) | + | |
| - | { | + | |
| - | if( !sets.empty() ) | + | |
| - | sets += ','; | + | |
| - | + | ||
| - | sets += "`" + col->first + "`='" + col->second + "'"; | + | |
| - | } | + | |
| - | + | ||
| - | query( "UPDATE " + table + " SET " + sets + " WHERE " + where ); | + | |
| - | } | + | |
| - | + | ||
| - | //-------------------------------------------------------------------------- | + | |
| - | void deleteFrom( const std::string& table, | + | |
| - | const Row& checks, | + | |
| - | const std::string& id_col ) | + | |
| - | { | + | |
| - | Result values = select(table, checks); | + | |
| - | + | ||
| - | for( Result::const_iterator row = values.begin(); | + | |
| - | row != values.end(); | + | |
| - | ++row ) | + | |
| - | { | + | |
| - | query( "DELETE FROM " + table | + | |
| - | + " WHERE `" + id_col + "`='" + row->at(id_col) + "'" ); | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | private: | + | |
| - | + | ||
| - | void checkCall( int retval ) | + | |
| - | { | + | |
| - | if( retval != SQLITE_OK ) | + | |
| - | throw std::runtime_error( sqlite3_errmsg(_db) ); | + | |
| - | } | + | |
| - | sqlite3* _db; | + | |
| - | }; | + | |
| - | </code>\\ | + | |
| - | + | ||
| - | Und ein Verwendungsbeispiel: | + | |
| - | <code cpp> | + | |
| - | int main(int argc, char* argv[]) | + | |
| - | { | + | |
| - | // open the database | + | |
| - | SQLite db("messages.db"); | + | |
| - | + | ||
| - | // create new entry | + | |
| - | SQLite::Row input; | + | |
| - | input["type" ] = argv[2]; | + | |
| - | input["host" ] = argv[3]; | + | |
| - | input["service" ] = argv[4]; | + | |
| - | input["state" ] = argv[5]; | + | |
| - | input["duration" ] = argv[6]; | + | |
| - | input["email" ] = argv[7]; | + | |
| - | + | ||
| - | std::cout << "Inserting new notification..." << std::endl; | + | |
| - | db.insert("messages", input); | + | |
| - | + | ||
| - | // print out the database | + | |
| - | SQLite::Result result = db.query("select * from messages"); | + | |
| - | + | ||
| - | for( SQLite::Result::iterator row = result.begin(); | + | |
| - | row != result.end(); | + | |
| - | ++row ) | + | |
| - | { | + | |
| - | std::cout << "-----------------------------------------------------------" | + | |
| - | << "---------------------" << std::endl; | + | |
| - | std::cout << row->at("id") << "|" | + | |
| - | << row->at("type") << "|" | + | |
| - | << row->at("host") << "|" | + | |
| - | << row->at("service") << "|" | + | |
| - | << row->at("state") << "|" | + | |
| - | << row->at("duration")<< "|" | + | |
| - | << row->at("inserted")<< "|" | + | |
| - | << row->at("message_sent") | + | |
| - | << std::endl; | + | |
| - | } | + | |
| - | + | ||
| - | return 0; | + | |
| - | } | + | |
| - | </code>\\ | + | |
| - | schema.sql: | + | |
| - | <code sql> | + | |
| - | DROP TABLE IF EXISTS messages; | + | |
| - | CREATE TABLE messages( | + | |
| - | id INTEGER PRIMARY KEY AUTOINCREMENT, | + | |
| - | inserted INTEGER NOT NULL DEFAULT 0, | + | |
| - | message_sent INTEGER NOT NULL DEFAULT 0, | + | |
| - | type TEXT, | + | |
| - | host TEXT, | + | |
| - | service TEXT, | + | |
| - | state TEXT, | + | |
| - | duration TEXT, | + | |
| - | email TEXT | + | |
| - | ); | + | |
| - | </code>\\ | + | |
| - | Datenbank in der Konsole erstellen: | + | |
| - | <code>sqlite3 messages.db < schema.sql</code> | + | |