如何使用QT转储SQLite DB的所有表?

时间:2014-03-26 10:28:59

标签: qt sqlite

我知道在SQLite中有一个功能可以转储所有表(到文件" createDBTablesScript.sql"),其中包含:

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

有没有办法在QT中做到这一点? 这样的事情(!这不工作!):<​​/ p>

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 );

2 个答案:

答案 0 :(得分:7)

.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;。< / p>

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

答案 1 :(得分:1)

最后我这样做了:

/**
* 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中重新创建db。

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