Как я могу повторно использовать объект запроса MySQL ++ для вызова нескольких хранимых процедур? - PullRequest
0 голосов
/ 08 марта 2011
#include <iostream>
#include <mysql++.h>
using namespace std;

int main() {
    // Get database access parameters from command line
    const char* db = "enet", *server = "192.168.1.108", *user = "root", *pass =
            "123456";
    // Connect to the sample database.
    mysqlpp::Connection conn(false);
    conn.set_option(new mysqlpp::MultiStatementsOption(true));
    if (conn.connect(db, server, user, pass)) {
        mysqlpp::Query query = conn.query();
        query << "call CreateTable('test1', 'generic', 0, 1, 2, 3,4,5,6,7,8,9,10,NOW());";
        query.execute();
        query.reset();

        query << "call CreateTable('test2', 'generic', 0, 1, 2, 3,4,5,6,7,8,9,10,NOW());";
        query.execute();
        query.reset();

        return 0;
    } else {
        cerr << "DB connection failed: " << conn.error() << endl;
        return 1;
    }

    return 0;
}

Я хочу использовать запрос mysql ++ для выполнения процедуры «CreateTable» много раз, и я, наконец, сбросил запрос, но независимо от того, как работает только первый запрос, последний не работает, моя проблема в том, чтокак заставить работать все запросы?

-- create table --
delimiter $$
drop procedure if exists CreateTable $$
create procedure CreateTable(
    IN tableName VARCHAR(20), 
    IN dbName VARCHAR(20),
    IN INT_RegDevID INTEGER,
    IN Dec_Long DECIMAL(24,16),
    IN Dec_Lat DECIMAL(24,16),
    IN Dec_Height DECIMAL(10,6),
    IN Dec_Direction DECIMAL(10,6),
    IN AverageSpeed DECIMAL(10,6),
    IN Dec_Base VARCHAR(10),
    IN MCC INTEGER,
    IN MNC INTEGER,
    IN LAC INTEGER,
    IN CI INTEGER,
    IN Dec_LocaDate TIMESTAMP)
-- -------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------
begin
    -- the test variable
    -- Warning: the encoding can result many problem!!!
    declare varTableName VARCHAR(32) default NULL;
    set @varTableName = NULL;
    set @table_prefix = "posinfo_";
    set @table_params = "(
          `Int_LocaID` int(11) NOT NULL auto_increment,
          `INT_RegDevID` int(11) NOT NULL default '0',
          `Dec_Long` decimal(24,16) NOT NULL default '0.0000000000000000',
          `Dec_Lat` decimal(24,16) NOT NULL default '0.0000000000000000',
          `Dec_Height` decimal(10,6) NOT NULL default '0.000000',
          `Dec_Direction` decimal(10,6) NOT NULL default '0.000000',
          `Dec_ MaxSpeed` decimal(10,6) NOT NULL default '0.000000',
          `Dec_ MinSpeed` decimal(10,6) NOT NULL default '0.000000',
          `AverageSpeed` decimal(10,6) NOT NULL default '0.000000',
          `Var_PosInfo` varchar(50) character set latin1 NOT NULL default '',
          `Var_Remark` varchar(200) character set latin1 NOT NULL default '',
          `Date_LocaDate` timestamp NOT NULL default CURRENT_TIMESTAMP,
          `Dec_Base` varchar(10) character set latin1 NOT NULL,
          `MCC` int(11) NOT NULL COMMENT '',
          `MNC` int(11) NOT NULL COMMENT '',
          `LAC` int(11) NOT NULL COMMENT '',
          `CI` int(11) NOT NULL COMMENT '',
          PRIMARY KEY  (`Int_LocaID`)
        ) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=gbk;";
    set @varCreate = CONCAT("create table ", dbName,".",@table_prefix, tableName, @table_params);
    -- the insert operation
    set @insertOperation = CONCAT("insert into ", dbName,".",@table_prefix, tableName,
        "(INT_RegDevID,Dec_Long,Dec_Lat,Dec_Height,Dec_Direction,AverageSpeed,
         Dec_Base,MCC,MNC,LAC,CI,Date_LocaDate) values(",INT_RegDevID,",",Dec_Long,
         ",",Dec_Lat,",",Dec_Height,",",Dec_Direction,",",AverageSpeed,",",Dec_Base,
         ",",MCC,",",MNC,",",LAC,",",CI,",NOW())"); 
    -- find the target table
    -- Look care about the "' '" !
    set @getTargetTable = CONCAT("select TABLE_NAME into @varTableName from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='",
        dbName, "' and TABLE_NAME='", @table_prefix, tableName,"'");

    -- -------------------------------------------------------------------------------
    -- -------------------------------------------------------------------------------
    PREPARE getTargetTable from @getTargetTable;
    execute getTargetTable;
    select @varTableName;
    set varTableName = @varTableName;

    if varTableName is NULL then
        -- create new table
        PREPARE newTable 
        from @varCreate;
        execute newTable;
        -- do insert operation
        PREPARE insertOperation
        from @insertOperation;
        execute insertOperation;

    else
        -- do insert operation
        PREPARE insertOperation
        from @insertOperation;
        execute insertOperation;
    end if;

end $$
delimiter ;

выше, это процедура.

1 Ответ

1 голос
/ 08 марта 2011

Здесь есть несколько ошибок:

  1. Вы отключили исключения (conn(false)), но также не проверяете возвращаемые значения для кодов ошибок. Ваш второй execute() звонок не работает, но, не спросив Query объекта, почему, вы бежите вслепую.

    Вместо того, чтобы добавлять проверку ошибок ко всем вызовам MySQL ++, я думаю, что было бы лучше, если бы MySQL ++ генерировал исключения (conn()) и помещал все это в блок try.

  2. Вам не нужно MultiStatementsOption, чтобы делать то, что вы спрашиваете так, как вы сейчас показываете. Здесь у вас есть два отдельных утверждения, а не одно сложное утверждение. Это в сочетании с точкой с запятой может сбивать с толку MySQL, поэтому второй вызов завершается неудачей.

    Инструмент командной строки mysql требует точки с запятой для завершения операторов SQL, но при использовании API базы данных, такого как MySQL ++, они необходимы только для разделения нескольких операторов.

    Вы можете либо объединить оба оператора CREATE в одну строку (и одну execute()), либо добавить точку с запятой и MultiStatementsOption.

  3. Вызовы reset() между запросами не нужны с MySQL ++ 2. x . Единственная причина, по которой метод все еще доступен, заключается в том, что это необходимо, если вы хотите повторно использовать объект Query, который использовался для шаблонных запросов; это единственный тип, который по-прежнему не имеет автоматического сброса по вполне очевидным причинам.

...