QtずSQLite、および䞀般に、Qtでのデヌタベヌスプログラミング

こんにちは



以䞋では、 Qtで SQLiteを䜿甚する方法に぀いお説明したす。 著者は、可胜な限りQtのデヌタベヌスプログラミングを怜蚎したした。



䞊蚘のリンクをたどるず、これらの2぀のすばらしい補品に぀いお読むこずができたす。特に、SQLiteの䟋を䜿甚しお、Qtでのデヌタベヌスプログラミングを具䜓的に怜蚎したす。 SQLiteは、クラむアントサヌバヌアヌキテクチャを持たないずいう点で、MySQLなどの「通垞の」デヌタベヌスずは倚少異なるずしか蚀えたせん。 ぀たり、デヌタベヌス゚ンゞンは、プログラムが察話する個別に動䜜するプロセスではありたせん。 SQLiteは、プログラムがリンクされるラむブラリであるため、゚ンゞンはプログラムの䞍可欠な郚分になりたす。 ぀たり、プログラムが「遭遇する」すべおのデヌタを通垞のファむルに保存するこずにしたず想像しおください。 ある晎れた日、デヌタをファむルに保存するこずにしたしたが、「リレヌショナル」の芳点から敎理したした。 その埌、新しいファむル構造を「特別な方法で認識する」必芁があるこずに気付きたした。 このこずから、少なくずも、このデヌタファむルずアプリケヌション間のリンクを提䟛するAPIを提䟛する必芁がありたす。 䞀般に、䞊蚘のシナリオの論理ステヌトメントに埓っお、デヌタベヌスサヌバヌず実際にはクラむアントを必芁ずしないデヌタベヌスシステムを䜜成したす。 「クラむアントサヌバヌ」デヌタベヌスシステムず比范しお非垞に高速であるこずが刀明し、プログラム自䜓が簡玠化されおいたす。



私はQtず友奜的な関係にあり、最近、そのDB機胜が必芁になりたした。 たた、MySQLずは友奜的な関係にあり、そのずきに開発しおいたプログラムでQtをMySQLで䜿甚しようずしたした。 MySQLをQtに「接続」するための時間ず神経が足りないので、SQLtを䜿甚するこずにしたした。 QtSqlモゞュヌルを接続せずに、「読み取り」モゞュヌルをサポヌトしお組み立おられたす。 それでも、別のコンピュヌタヌにプログラムをむンストヌルする必芁がある堎合、MySQLサヌバヌなどのむンストヌルを「匷制」されるこずはありたせん。 物議を醞すトピック-私は知っおいたす。



ファむ



珟時点では、 SQLiteManagerプログラムを䜿甚しおデヌタベヌス、テヌブルなどを䜜成しおいたす。最近䜿甚したしたが、すぐにプログラムが気に入りたした。 私の「䞻力補品」にはa Qt Windows SDKがむンストヌルされおおり、 QtCreatorを䜿甚しおいたす。すぐにそれが茝いおいるず蚀いたす 私芋ではなく、本圓に玠晎らしいIDEです 。



そしお、Qtずデヌタベヌス



䞊蚘ですでに暗黙的に蚀及したように、Qtには、デヌタベヌスを䜿甚するための䟿利な「サヌビス」を提䟛する別のモゞュヌル-QtSqlがありたす。 Qtの経隓がある堎合は、.proファむルに぀いお知っおいたす。そうでなければ、 知り合いになりたす。 .proファむルに次の行を远加する必芁があるこずを忘れないでください。

QT += sql
      
      





これはQtSqlモゞュヌルを䜿甚し、そのクラスを操䜜するために、同じタむトルを含める必芁がありたす。

 #include <QtSql>
      
      





Qtブックでは、QtSqlモゞュヌルの3぀のレベルに぀いお説明しおいたす。

  1. ドラむバヌレベル
  2. プログラムレベル
  3. ナヌザヌむンタヌフェむスレベル
ドラむバヌレベル


ドラむバレベルには、次のような物理レベルでデヌタを受信するためのクラスが含たれたす。

QSqlDriverは、特定のデヌタベヌスにアクセスするために蚭蚈された抜象基本クラスです。 クラスを「盎接」䜿甚しないようにするこずが重芁であり、代わりにQSqlDatabaseが必芁/䜿甚できたす。 ただし、独自のSQLドラむバヌを䜜成する堎合は、 QSqlDriverから継承しお、必芁な仮想関数ず仮想関数を実装できたす。

QSqlDriverCreatorは、特定の皮類のドラむバヌにSQLドラむバヌファクトリヌを提䟛するテンプレヌトクラスです。 テンプレヌトパラメヌタヌはQSqlDriverのサブクラスである必芁がありたす。

QSqlCreatorBaseは、SQLドラむバヌファクトリヌの基本クラスであり、提䟛するQSqlDriverクラスの特定のサブクラスのむンスタンスを返すには、 createObjectメ゜ッドを「蚀い換える」必芁がありたす。

QSqlDatabaseは、デヌタベヌスドラむバヌプラグむンの読み蟌みず管理を担圓したす。 デヌタベヌスが远加されるずこれはQSqlDatabase :: addDatabase関数によっお行われたす、必芁なドラむバヌプラグむンが QSqlDriverPluginを䜿甚しおロヌドされたす。 QSqlDriverPluginは、カスタムQSqlDriverプラグむンの抜象基本クラスを提䟛したす。

QSqlResult自䜓はすべおのQtクラスのようにそれ自䜓に぀いお語り、このクラスは特定のデヌタベヌスのデヌタにアクセスするための抜象むンタヌフェヌスを提䟛したす。 QSqlQueryはQSqlResultの DB固有の実装のラッパヌ「䞀般化」を提䟛するため、実甚的な芳点から、 QSqlResultの代わりにQSqlQueryを䜿甚したす。

したがっお、ドラむバヌのレベルは、独自のドラむバヌを䜜成するずきに䜿甚するこずが重芁であるため、ドラむバヌのフレヌムワヌクずしお䜿甚できる最も関心のあるコヌドの䟋を瀺したす。



 class XyzResult : public QSqlResult { public: XyzResult(const QSqlDriver *driver) : QSqlResult(driver) {} ~XyzResult() {} protected: QVariant data(int /* index */) { return QVariant(); } bool isNull(int /* index */) { return false; } bool reset(const QString & /* query */) { return false; } bool fetch(int /* index */) { return false; } bool fetchFirst() { return false; } bool fetchLast() { return false; } int size() { return 0; } int numRowsAffected() { return 0; } QSqlRecord record() const { return QSqlRecord(); } }; class XyzDriver : public QSqlDriver { public: XyzDriver() {} ~XyzDriver() {} bool hasFeature(DriverFeature /* feature */) const { return false; } bool open(const QString & /* db */, const QString & /* user */, const QString & /* password */, const QString & /* host */, int /* port */, const QString & /* options */) { return false; } void close() {} QSqlResult *createResult() const { return new XyzResult(this); } };
      
      







プログラムレベル


デヌタベヌスに接続するには、たず静的メ゜ッドQSqlDatabase :: addDatabaseを䜿甚しおドラむバヌをアクティブにする必芁がありたす。 メ゜ッドは、DBMSドラむバの識別子を瀺す文字列を匕数ずしお受け取りたす。 QSQLITEが必芁になりたす。



 QSqlDatabase sdb = QSqlDatabase::addDatabase("QSQLITE"); sdb.setDatabaseName("db_name.sqlite"); if (!sdb.open()) { //.... }
      
      





addDatabase静的関数には、ドラむバヌ名ではなくドラむバヌ自䜓 QSqlDriver *を受け取るオヌバヌロヌドされた「兄匟」がありたす。

接続はopenメ゜ッドを䜿甚しお行われたす。 QSqlDatabaseクラスは、デヌタベヌス接続を衚したす。 接続は、サポヌトされおいるデヌタベヌスドラむバヌを介したデヌタベヌスぞのアクセスを提䟛したす。 同じデヌタベヌスに耇数の接続を確立できるこずが重芁です。

接続䞭に゚ラヌが発生した堎合 openメ゜ッド 、゚ラヌに関する情報はQSqlDatabase :: lastErrorメ゜ッドから取埗できたす QSqlErrorを返したす。



 if (!sdb.open()) { qDebug() << sdb.lastError().text(); }
      
      





Qtを䜿甚しおSQLコマンドを実行する方法を怜蚎しおください。 QSqlQueryクラスを䜿甚しおこれを行うこずができたす。 このクラスは、 SELECT 、 INSERT 、 UPDATE 、 DELETEなどのDMLデヌタ操䜜蚀語匏の実行だけでなく、 CREATE TABLEなどのDDLデヌタ定矩蚀語匏の実行にも䜿甚できたす。 SQL暙準ではないDB固有のコマンドを実行できるこずに泚意しおくださいたずえば、PSQLの堎合-「SET DATESTYLE = ISO」。

正垞に実行されたリク゚ストはリク゚ストのステヌタスを「アクティブ」に蚭定するため、 isActiveは true を返したす 。そうでない堎合、状態は非アクティブに蚭定されたす。 ク゚リは通垞の文字列の圢匏で発行され、コンストラクタヌたたはQSqlQuery :: execメ゜ッドに枡されたす。 最初のケヌスでは、コンストラクタヌに枡すずきに、コマンドが自動的に起動されたすオブゞェクトの構築時。

非垞に興味深いのは、 QSqlQueryが提䟛するナビゲヌション機胜です 。 たずえば、 SELECTク゚リの埌、 next、previous、first、last、およびseekメ゜ッドを䜿甚しお、収集されたデヌタをナビゲヌトできたす。



 QSqlQuery query("SELECT country FROM artist"); while (query.next()) { QString country = query.value(0).toString(); do_something(country); }
      
      





nextメ゜ッドを䜿甚するず、デヌタの次の行に移動し、前の行にそれぞれpreviousを呌び出すこずができたす。 first、lastは、それぞれ結果から最初のレコヌドを取埗したす。 seekは敎数むンデックスを取埗し、受信したむンデックスの結果からレコヌドを取埗し、抜出されたレコヌドに「ク゚リを配眮」したす。 サむズメ゜ッドを䜿甚しお、サむズ、たたはデヌタの行数結果を確認できたす。 最初のレコヌドが䜍眮0にあり、ク゚リがアクティブな状態である必芁があり、 isSelect がtrue 最埌のク゚リがSELECTの堎合に発生を返しおからseekメ゜ッドを呌び出すこずに泚意しおください。 公匏ドキュメントの seek メ゜ッドに぀いお詳しく読むこずをお勧めしたす。

ク゚リ文字列をQSqlQueryクラスのコンストラクタに枡すず、オブゞェクトの䜜成時に-構築䞭にク゚リが実行されるこずを䞊で述べたした。 exec メ゜ッドを䜿甚するず、いわば、リク゚ストの実行時間を監芖できたす。 建蚭業

 QSqlQuery query("SELECT country FROM artist");
      
      



次のように衚すこずもできたす。

 QSqlQuery query; query.exec("SELECT country FROM artist");
      
      



そのため、 exec は芁求をQStringずしお受け取りたす。 リク゚ストが満たされるず、成功した堎合、このメ゜ッドはtrueを返し、状態をアクティブに蚭定したす。それ以倖の堎合、すべおは瀺された操䜜ず「反察」になりたす。 もちろん、ク゚リ文字列は、芁求されたデヌタベヌス特にSQL暙準の構文芏則に埓う必芁があるこずも芚えおおく必芁がありたす。

興味深いのは、実行埌、芁求が無効なuyレコヌドに配眮されるこずです。぀たり、結果を適切に䜿甚するには、たずえばnext メ゜ッドを䜿甚する必芁がありたす。

exec メ゜ッドには、匕数を受け取らないオヌバヌロヌドされた代替がありたす。 このバリアントexec の呌び出しは、この前に準備された芁求を実行したす。 泚意しおください-「準備枈み」。 これを行うには、芁求の準備が成功した堎合にtrueを返すprepare メ゜ッドを䜿甚したす。

メ゜ッドの重芁性、たたは蚀えるこずは、 bindValue を䜿甚しお倀をバむンドするための「プレヌスホルダヌ」をリク゚ストに含めるこずができるこずです。

 QSqlQuery my_query; my_query.prepare("INSERT INTO my_table (number, address, age)" "VALUES (:number, :address, :age);"); my_query.bindValue(":number", "14"); my_query.bindValue(":address", "hello world str."); my_query.bindValue(":age", "37");
      
      





匿名パラメヌタヌのオプションを䜿甚するこずもできたす。



 QSqlQuery my_query; my_query.prepare("INSERT INTO my_table (number, address, age)" "VALUES (?, ?, ?);"); my_query.bindValue("14"); my_query.bindValue("hello world str."); my_query.bindValue("37");
      
      





最埌に、QStringが提䟛するむンラむン匕数を単玔に䜿甚できたす。



 QSqlQuery my_query; my_query.prepare( QString("INSERT INTO my_table (number, address, age) VALUES (%1, '%2', %3);") .arg("14").arg("hello world str.").arg("37") );
      
      





コンパむル枈みコピヌしお貌り付けお自分のアむデアに​​の䟋



 #include <QtGui/QApplication> #include <QtSql> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QSqlDatabase dbase = QSqlDatabase::addDatabase("QSQLITE"); dbase.setDatabaseName("my_db.sqlite"); if (!dbase.open()) { qDebug() << "-   !"; return -1; } QSqlQuery a_query; // DDL query QString str = "CREATE TABLE my_table (" "number integer PRIMARY KEY NOT NULL, " "address VARCHAR(255), " "age integer" ");"; bool b = a_query.exec(str); if (!b) { qDebug() << "    ,  !"; } // DML QString str_insert = "INSERT INTO my_table(number, address, age) " "VALUES (%1, '%2', %3);"; str = str_insert.arg("14") .arg("hello world str.") .arg("37"); b = a_query.exec(str); if (!b) { qDebug() << "   ,  ,   ?"; } //..... if (!a_query.exec("SELECT * FROM my_table")) { qDebug() << "   ,  ."; return -2; } QSqlRecord rec = a_query.record(); int number = 0, age = 0; QString address = ""; while (a_query.next()) { number = a_query.value(rec.indexOf("number")).toInt(); age = a_query.value(rec.indexOf("age")).toInt(); address = a_query.value(rec.indexOf("address")).toString(); qDebug() << "number is " << number << ". age is " << age << ". address" << address; } return app.exec(); }
      
      





ク゚リ結果を取埗するには、 QSqlQuery :: valueメ゜ッドを呌び出す必芁がありたす。このメ゜ッドでは、䟋でrecord メ゜ッドが䜿甚された列番号を枡す必芁がありたす。 このメ゜ッドは、 SELECTク゚リに関連する情報を含むQSqlRecordクラスのオブゞェクトを返したす。 QSqlRecord :: indexOfを呌び出すこずにより、列むンデックスを取埗したす。

valueメ゜ッドはQVariant型オブゞェクトに異なる型の倀を含めるこずができるクラスの倀を返すため、メ゜ッドQVariant :: toIntおよびQVariant :: toStringを䜿甚しお結果の倀を倉換したした。



ナヌザヌむンタヌフェむスレベル


QtSqlモゞュヌルは、プレれンテヌションで䜿甚するための倚数のモデルを提䟛するこずにより、むンタビュヌの抂念をサポヌトしおいたす。 この抂念に慣れるには、 こちらをご芧ください 。

䟋ずしお、 QSqlTableModelクラスを䜿甚するず、デヌタを衚圢匏および階局圢匏で衚瀺できたす。 文献によるず、むンタビュヌは衚デヌタを衚瀺する最も簡単な方法であり、ここでは衚の行を調べるサむクルは必芁ありたせん。 以䞋に小さな䟋を瀺したす。



 #include <QtGui/QApplication> #include <QtSql> #include <QTableView> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QSqlDatabase dbase = QSqlDatabase::addDatabase("QSQLITE"); dbase.setDatabaseName("my_db.sqlite"); if (!dbase.open()) { qDebug() << "-    !"; return -1; } QTableView view; QSqlTableModel model; model.setTable("my_table"); model.select(); model.setEditStrategy(QSqlTableModel::OnFieldChange); view.setModel(&model); view.show(); return app.exec(); }
      
      





接続埌、 QTableViewテヌブルビュヌオブゞェクトずQSqlTableModelテヌブルモデルオブゞェクトが䜜成されたす。 setTable メ゜ッドはモデルの珟圚のベヌスを蚭定し、 select 呌び出しはデヌタで満たされたす。

QSqlTableModelクラスは、次の線集戊略を提䟛したす setEditStrategy を䜿甚しお蚭定



投皿はあずがきに近づいたず思いたす。誰かが圌が探しおいるものをここで芋぀け、誰かが「埌で」情報を必芁ずするこずを望みたした。



All Articles