【问题标题】:How to dump all tables of a SQLite DB with QT?如何使用 QT 转储 SQLite DB 的所有表?
【发布时间】:2014-03-26 10:28:59
【问题描述】:

我知道在 SQLite 中有一个转储所有表的功能(到文件“createDBTablesScript.sql”):

sqlite> .output createDBTablesScript.sql
sqlite> .dump
sqlite> .quit

有没有办法在 QT 中做到这一点? 像这样的东西(!这不起作用!):

QString  queryString(".output createDBTablesScript.sql .dump");
QSqlQuery query( m_db );
bool checkQueryExcecution = query.exec( queryString );

之后我也想从 QT 运行脚本,例如:

QString  createDBTablesScriptString("run createDBTablesScript.sql");
QSqlQuery query( m_db );
bool checkQueryExcecution = query.exec( createDBTablesScriptString );

【问题讨论】:

    标签: qt sqlite


    【解决方案1】:

    .dump 命令在sqlite 命令行应用程序中实现,而不是在 SQLite 库本身中实现。 .dump 使用标准 SQL 查询从数据库中提取所需的一切。你也可以这样做,但不仅仅是 3 行。

    它看起来像这样:

    QSqlQuery query;
    QStringList tables;
    query.prepare("SELECT * FROM sqlite_master");
    while (query.next())
    {
        qDebug() << query.value("sql").toString();
        if (query.value("type").toString() == "table")
            tables << query.value("name");
    }
    
    static const QString insert = QStringLiteral("INSERT INTO %1 (%2) VALUES (%3);");
    QStringList columns;
    QStringList values;
    QSqlRecord record;
    bool first = true;
    foreach (const QString& table, tables)
    {
        first = true;
        query.prepare(QString("SELECT * FROM [%1]").arg(table));
        while (query.next())
        {
            record = query.record();
            for (int i = 0; i < record.count(); i++)
            {
                if (first)
                    columns << record.fieldName(i);
    
                values << record.value(i);
            }
            first = false;
    
            qDebug() << insert.arg(table).arg(columns.join(", ")).arg(values.join(", "));
        }
    }
    

    几点说明:

    1. 我是凭脑子写的,没有测试过,所以可能有一些错误,但你明白了。

    2. 这不包括.dump 生成的其他查询,例如开头的BEGIN;PRAGMA foreign_keys = 0;,然后是结尾的COMMIT;

    3. .dump 在某些我不知道的特殊情况下可能会生成更多查询。我只是尝试在包含 2 个表的测试数据库上运行 .dump,结果这些都是我找到的语句。

    【讨论】:

      【解决方案2】:

      我终于做到了:

      /**
      * This function should do something similar to :
      *
      * sqlite> .output "t_fileName" --f.e. "createEmptyDBTablesScript.sql"
      * sqlite> .dump
      *
      * this function dumps not the values, it dumps only the table schemas (the CREATE TABLE statement)!
      */
      bool
      DBAccess::dumpDBTableSchemasToFile
      (
         const QString &t_fileName, 
         const QString &t_createTableStatementSeperator /* = QString("--;;")  */
      )
      {
         bool r_dumpingSuccessfull = false;
      
         if( m_db.open() ) //QSqlDatabase m_db; //qt connection to sqlite database
         {
            qDebug() << "Dump the Database Schemas to file "+ t_fileName;
      
            QFile outputFile(t_fileName);
            outputFile.open(QIODevice::WriteOnly);
      
            /* Check if File opening was OK */
            if( !outputFile.isOpen() )
            {
               qDebug() << "- Error, unable to open '" << t_fileName << "' to dump SQL for table creation!";
               return r_dumpingSuccessfull;
            }
      
            /* Point a QTextStream object at the file */
            QTextStream outStream(&outputFile);
      
            /* Ask the 'sqlite_master' table of the sqlite Database with a SELECT statement for all tables, the 'sql' column holds the sql-CREATE TABLE statement which created the current table. */
            QSqlQuery sqlite_masterQuery( m_db );
            if( !sqlite_masterQuery.exec( "SELECT * FROM sqlite_master" ) )
            {
               //Something with the SQL-Query or the DB-connection is wrong.
               QString lastError = sqlite_masterQuery.lastError().text(); 
               qDebug() << lastError;
               return r_dumpingSuccessfull;
            }
            else
            {
               //Here we got some valid results from the sql-query above
               do
               {
                  QString tableName = sqlite_masterQuery.value("name").toString();
                  if( sqlite_masterQuery.value("type").toString() == "table" && tableName != "sqlite_sequence" )//The "sqlite_sequence" table is an internal table used to help implement AUTOINCREMENT 
                  {
                     /* Write the 'sql' column value to the file, the 'sql' column value represent the 'CREATE TABLE xyz...' sql statement */
                     outStream << sqlite_masterQuery.value("sql").toString();
                     outStream << "\n";
                     outStream << t_createTableStatementSeperator;
                     outStream << "\n";
      
                     r_dumpingSuccessfull = true;
                  }
               } while( sqlite_masterQuery.next() );
            }
      
            outputFile.close();/* Close the dump-file */
         }
      
         return r_dumpingSuccessfull;
      }
      

      这是经过测试并且有效的。 有了这个:

      bool 
      DBAccess::createDBTableSchemasFromFile
      (
         const QString &t_fileName, 
         const QString &t_createTableStatementSeperator /* = QString("--;;")  */
      )
      {
         bool r_creationSuccessfull = false;
      
         if( m_db.open() ) 
         {
            qDebug() << "Creating the empty tables of the Database from file "+ t_fileName;
      
            QFile outputFileRead( t_fileName );
            if( !outputFileRead.open( QIODevice::ReadOnly | QIODevice::Text ) )
               return r_creationSuccessfull;
      
            QTextStream sqlTableCreationScriptTextStream( &outputFileRead );
            QString sqlTableCreationDataWholeString      = sqlTableCreationScriptTextStream.readAll();
            QStringList seperateCreatTableStatementsList = sqlTableCreationDataWholeString.split( t_createTableStatementSeperator );
            foreach( const QString& creatTableStatement, seperateCreatTableStatementsList )
            {
               qDebug() << creatTableStatement;
      
               if( creatTableStatement.simplified().isEmpty() )
                  continue;
      
               QSqlQuery query( m_db );
               if( !query.exec( creatTableStatement ) )
               {
                  QString lastError = query.lastError().text(); 
                  qDebug() << lastError;
                  r_creationSuccessfull = false;  
                  break;
               }
      
               r_creationSuccessfull = true;
            }
         }
      
         return r_creationSuccessfull;
      }
      

      也可以从转储的 sql 中重新创建数据库。

      正如 Googie 已经说过的:“你也可以这样做,但不仅仅是 3 行。”

      【讨论】:

        猜你喜欢
        • 2017-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-07
        • 2020-12-30
        • 2022-01-15
        • 1970-01-01
        相关资源
        最近更新 更多