quarta-feira, 4 de março de 2009

Acesso a banco de dados MySQL


Olá pessoal...

Bom sendo este o meu primeiro post aqui no Include C/C++ e este post se destina a criar uma aplicação que tenha acesso a um banco de dados MySQL. Então vamos lá, agora que vocês já devem ter tudo funcionando 100% após ter lido o post Compilando C/C++ no Linux e no Windows.

Agora então agora é necessário instalar o servidor de banco de dados MySQL. No linux basta digitar apt-get install mysql-server-X.X onde X é a versão. Nós iremos utilizar a 5.0 (mysql-server-5.0). São aproximadamente 36MB. Após baixado e instalado uma senha é requisitada, eu utilizei a famosa senha 123.

Para que se consiga utilizar a biblioteca mysql é necessário baixar a libmysqlclient-dev, também através do apt-get.

Com o serviço instalado vamos criar as tabelas, para isto abra um terminal e digite mysql --user=root -p, então pedirá uma senha, esta senha é do root do MySQL então vamos inserir a senha que você definiu (no meu caso 123) e pronto estamos conectados com o serviço. Vamos então digitar...


create database acessodb;

connect acessodb;

CREATE TABLE `usuarios` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`usuario` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5;

INSERT INTO `usuarios` (`id`, `usuario`) VALUES
(1, 'Mauricio Sipmann'),
(2, 'Bolivar Arthur Butzke'),
(3, 'Helton Ritter'),
(4, 'Michel de Sousa');


Então ta, criamos um banco de dados, criamos a tabela e inserimos uns dados para podermos testar o banco, para sair do serviço basta digitar exit. Agora para conectar

Feito isto vamos para o código-fonte do progrma em C++.


#include // Para usar o cin.get
#include // mysql/mysql.h biblioteca mysql
#include // para usar o istringstream

using namespace std;

int main(void)
{
MYSQL DBCon; // Vairiavel de conexão
MYSQL_RES *result; //variável que recebe o resultado
MYSQL_ROW dados; //variável que recebe os dados

int ID; // Converter para integer

// Inicia a variável DBCon
mysql_init(&DBCon);

//Conecta com o banco de dados
if ( mysql_real_connect(&DBCon, "127.0.0.1", "root", "", "acessoaobd", 0, NULL, 0) )
{
printf("Conectado!\n\n");
}
else
{
//Escreve o erro que ocorreu
printf("Erro n %d : %s\n", mysql_errno(&DBCon), mysql_error(&DBCon));
cin.get(); //Espera o usuário pressionar uma tecla
cin.get();
return 1;
}

// Executa a consulta
if(mysql_query(&DBCon,"select * from usuarios"))
{
printf("Erro n %d : %s\n",mysql_errno(&DBCon),mysql_error(&DBCon));
cin.get();
cin.get();
return 1;
}

// Recebe os dados da cunsulta
result = mysql_store_result(&DBCon);

// Se consultou (sem erros)
if (result)
{
// Enquanto receber dados vai escrevendo
while ((dados=mysql_fetch_row(result)) != NULL)
{
// Escreve os dados formatados sende estes a ID e o NOME

istringstream buffer(dados[0]); // Cria a variável que recebera a string a ser convertida para int
buffer >> ID; // Convert a string para int
printf("%02d %s\n",ID,dados[1]); // Escreve formatado
}

// Limpa da memória
mysql_free_result(result);

}
else
{
printf("Erro n %d : %s\n", mysql_errno(&DBCon), mysql_error(&DBCon));
cin.get();
cin.get();
return 1;
}
printf("\n");
// Fecha a conexão ...
mysql_close(&DBCon);

return 0;
}

Então vamos as explicações. As primeiras linhas fazem referência às bibliotecas que iremos utilizar, iostream para as funções cout e cin, mysql.h para acessarmos o banco de dados, e sstream para convertermos as variáveis de string para int. O código quinta linha tem a função de minimizar o trabalho teriamos quando utilizássemos o cin.get ou cout << "texto", teríamos que escrever sempre std::cout << "" com este using namespace STD poupamos trabalho. Então definimos as variáveis DBCon, result, dados e ID, a variável DBCon é a nossa conexão com o banco, result é a variável que armazena o resultado de uma consulta e a variável dados é que receberá os dados de cada linha para escrevermos (veremos mais adiante nas explicações). A função mysql_ini(&DBCon) tem a finalidade de incializar a variável de conexão com o banco pois precisaremos dela diversas vezes como verão. Agora uma parte interessante e que vai do gosto de cada um. Existem 2 funções para se conectar com o banco de dados, são elas:
  • MYSQL * mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd);
  • MYSQL * mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned int clientflag);
A diferença é que na mysql_real_connet nós já especificamos o banco ao qual queremos nos conectar, já a mysql_connect só conecta e então seria necessário o uso da função mysql_select_db. Nós usaremos a real_connect, onde são necessários os seguintes parâmetros:



mysql_real_connect(variavel_de_conexao(&DBCon),"servidor(127.0.0.1)","usuario(root)","senha(123)","banco_de_dados(acessodb)",porta_de_conexão(0 para padrão),socket(NULL para padrão), flags_do_cliente(0 para padrão));




Caso ocorra algum erro utilizamos a função printf("Erro n %d: %s",mysql_errno(&DBCon), mysql_error(&DBCon)) onde formatamos para receber um inteiro e uma string, onde mysql_errno traz o numero do erro e mysql_error traz a mensagem de erro, então adicionamos 2 vezes cin.get() e um return 1 para que espere o usuário pressionar qualquer tecla para que finalize o programa.

Então chegamos a parte de execução de uma consulta com o mysql_query(&DBCon,"select * from usuarios"), então esta na cara, variável de conexão e em seguida a nossa SQL de seleção, e também é claro um tratamento de erro.

O pŕoximo passo então é armazenar o resultado completo da consulta em uma variável que é a variável result, result = mysql_store_result(&DBCon), esta função é necessário somente passar a variável de conexão, e como padrão checar se não houve erros durante a seleção. Após tudo isto chegamos na parte em que os dados serão exibidos... para isto é necessário fazer um laço para percorrer todas as linhas que retornaram do banco de dados, por isso o while, onde a variável dados recebe a linha atual, ele se transforma numa array.

É dentro do laço que é feito a conversão do campo ID que é string para int para que assim seja possível formatar o valor retornado com o printf.

istringstream buffer(dados[0]); // Cria a variável e já atribui o valor para ela
buffer >> ID; // Convert a string para int

Portanto o índice 0 da array dados é a ID, então o indece 1 é o campo usuário, e assim segue para cada campo seguinte. A formatação usada no printf %02d é utilizada para que sempre seja impresso numero com 2 casas decimais... EX: 04

Concluindo o código o mysql_free_result limpa da memória a pesquisa e o mysql_close encerra a conexão com o banco de dados. Bom, código feito, é hora de compilar, no linux para compilar (lembrando que este é um código C++) seria:

  • g++ -c arquivo.cpp -lmysqlclient

  • g++ -o arquivo arquivo.o -lmysqlclient



Bom... Para que este -lmysqlclient?? Ele é usado para associar a libmysql-cliet-dev que nós baixamos antes ao nosso sistema.

Então esta ai. Espero que tenham gostado. Até a próxima...

26 comentários:

  1. Show de bola trabalhar com C++ e MySQL. Outro nível agora! :)

    ResponderExcluir
  2. Incrivel seu post, muito dificil encontrar algo assim, parabens!!!

    ResponderExcluir
  3. Realmente outro nivel! Gosto muito do Hellow world, mas este surpreendeu! parabéns

    ResponderExcluir
  4. Alem de C++, isso também funciona para C? Thanks pela resposta futura.

    ResponderExcluir
    Respostas
    1. Sim, a idéia a mesma. Qualquer dúvida é só pedir. Abraço

      Excluir
  5. Oi Mauricio, otimo post.
    Gostaria de aprender a sintaxe para usar o " ... WHERE campo LIKE 'variavel que for definida pelo usuario'" , para pesquisa de um nome no banco de dados.
    Se alguem souber por favor me ensina, ja rodei a web e nada.
    Abraco.

    Joao

    ResponderExcluir
    Respostas
    1. Opa.... obrigado...
      Mas poderia me detalhar melhor a sua dúvida??? Pois a princípio pelo o que eu entendi, seria só adicionar o que você mesmo relatou...

      Excluir
    2. E aí Mauricio, por 5 minutos não vi sua resposta, tive que sair ontem, mas obrigado.
      Então, eu preciso que neste trecho de código " // Executa a consulta
      if(mysql_query(&DBCon,"select * from usuarios")) ", fique assim "// Executa a consulta
      if(mysql_query(&DBCon,"select * from usuarios where usuario like '%Mauricio%'"))", só que este '%Mauricio%' terá no lugar um variável que estarei guardando o seu valor com o método
      cin.getline(nome), então ficaria assim "// Executa a consulta
      if(mysql_query(&DBCon,"select * from usuarios where usuario like '%nome%'"))", mas não dá certo, não retorna nada da consulta, então deve ser a sintaxe.Se você puder me dar uma ajuda desde já te agradeço. Abraço. João

      Excluir
    3. Opa.... Infelizmente estou sem nenhum compilador C/C++ aqui para testar.... mas creio que basta fazer isto::

      if(mysql_query(&DBCon,"select * from usuarios where usuario like '%"+nome+"%'"))",

      Pois como é uma variável então você deve concatenar na sua string... por isso eu fechei as aspas e então coloquei a variável e novamente as aspas, sempre unindo com um +

      Qualquer dúvida estou ai...
      Abraços

      Excluir
  6. Mauricio valeu mesmo pela resposta, tentei desta forma, mas recebi o erro :
    "conectabd.cpp: In function ‘int main()’:
    conectabd.cpp:36:79: error: cannot convert ‘std::basic_string’ to ‘const char*’ for argument ‘2’ to ‘int mysql_query(MYSQL*, const char*)’"
    Não sei o que pode ser, mas parece que não aceita tipo string como argumento.
    Valeu pela ajuda, caso você encontre uma solução coloca aí pra gente, se eu conseguir eu coloco
    aqui também, obrigado, abraço.
    João

    ResponderExcluir
  7. void inserirFuncionario(int n, string funcionario) {
    int resquery; //cria uma variável para manter o resultado da consulta
    MYSQL con; // cria a variável de conexão
    mysql_init(&con); //inicializa a variável de conexão
    mysql_real_connect(&con, "localhost", "root", "123", "acessodb", 0, NULL, 0);
    //efetua a conexão, não esqueça de colocar o nome do seu banco de dados com os dados de usuario, senha e servidor.
    printf("Conectado com sucesso \n");

    resquery = mysql_query (&con, "Insert into `usuarios` (`id`, `usuario`) values (10 , 'funcionario' );");

    //insere dados na tabela cliente
    printf ("Registro inserido %d\n", mysql_affected_rows(&con));
    //apresenta o resultado da inserção na tabela e com a função mysql_affected_rows mostra quantas linhas foram inseridas no banco de dados.
    mysql_close(&con);
    //fecha a conexão
    system("pause");
    return;
    }

    Boa tarde, quero que essa função USE O INSERT ATRAVÉS DE VARIAVEIS, ONDE 'funcionario' seria uma variavel e o 10 tambem para usuario digitar e inserir, uma string.

    att, espero que entendam o que quero, não consegui achar uma forma pra isso.

    desde ja agradeço. ;)

    ResponderExcluir
  8. Eu não consegui fazer a conexão com o banco de dados, eu programa em c faz um bom tempo, e em php também. Teria como você fazer uma video aula explicando?

    ResponderExcluir
    Respostas
    1. Boa Tarde,

      cara, infelizmente estou com pouco tempo livre para conseguir fazer uma video aula, mas se precisar de ajuda, da um grito ai no que deu problema e tentarei responder.

      Excluir
  9. Por que você usou printf que é de c em vez de cout que é de c++?? Qual a diferença?

    ResponderExcluir
  10. Na verdade para o ex. em questão... nenhuma diferença não amigo.

    ResponderExcluir
  11. Ola Mauricio,

    Antes de mais tenho de dizer que sou novo nestas andanças e estou aprendendo a programar em C++ usando banco de dados.
    Depois ultrapassar (penso eu) a localização da biblioteca mysql.h, agora deparo-me com erros deste tipo:

    Sem Título1.cpp:(.text+0x157): undefined reference to `mysql_errno'

    O que significa e como posso resolver?
    Obrigado.
    Daniel Costa

    ResponderExcluir
    Respostas
    1. Buenas, desculpe a demora.
      Cara, acho que este link aqui é exatamente a sua dúvida::
      http://www.vivaolinux.com.br/topico/C-C++/MySQL-no-C

      Excluir
  12. oi como faço pra inserir a bibliotecnia no dev c

    ResponderExcluir
  13. Este comentário foi removido pelo autor.

    ResponderExcluir
  14. Muito bom esse post, e, consegui fazer a programação sem maiores problemas. Mas gostaria de saber como usar o "select count(*) from usuarios" pois, tentei e ele não me retorna a qntde de itens inseridos na tabela. Estou passando o resultado para um inteiro para verificar:

    int num = mysql_query(&DBCon,"select count(*) from usuarios");

    E sempre obtenho o resultado ZERO!!!

    O que estou fazendo de errado???

    ResponderExcluir
    Respostas
    1. Opa, bem simples, o resultado da função `mysql_query` não retorna o resultado da SQL, mas sim o resultado da execução em si, se rodou ou não. Para extrair os dados é algo semelhante a isto.

      Esta um pouco mais abaixo da linha ali em cima no tutorial.

      // Recebe os dados da cunsulta
      result = mysql_store_result(&DBCon);

      // Se consultou (sem erros)
      if (result)
      {
      // Enquanto receber dados vai escrevendo
      while ((dados=mysql_fetch_row(result)) != NULL)
      {

      /////////////////////

      Qualquer dúvida só pedir. abraços

      Excluir
  15. Este comentário foi removido pelo autor.

    ResponderExcluir
  16. Boa noite Mauricio Sipmann, agradeço pelo excelente post e pela dedicação nas respostas. Tentarei ser direto para não incomodar muito, estou tendo problemas na saída da consulta OBS: estou no Windows e usando C puro no CodeBlocks, o código compila e executa mas os nomes dos campos das tabelas saem errado no console quando existem mais de dois campos na tabela Ex:
    consulta "SELECT * FROM tb_alunos;" com os campos (ID Nome Idade CPF Curso)

    Acontece que os campos (Idade CPF Curso) são trocados pelo nome da tabela e do banco. Seguindo vários tutoriais incluindo este, fiz o Crud básico mas o select deu esse erro e não consigo descobrir o motivo, sintaticamente o código está idêntico a vários exemplos na internet, se puder me ajudar eu agradeço, a parte mais importante do código está aqui em baixo, obrigado e me desculpe por qualquer incomodo.

    if (mysql_query(&conexao, sqlConsulta)) {
    printf("Erro: %s\n", mysql_error(&conexao));
    } else {
    res = mysql_store_result(&conexao);
    if (res) {
    campos = mysql_fetch_fields(res);
    for (conta = 0; conta < mysql_num_fields(res); conta++) {
    printf("|%s|", (campos[conta]).name);
    if (mysql_num_fields(res) > 1) {
    printf("\t");
    }
    }
    printf("\n");
    while ((linhas = mysql_fetch_row(res)) != NULL) {
    for (conta = 0; conta < mysql_num_fields(res); conta++) {
    printf("%s\t", linhas[conta]);
    }
    printf("\n");
    }
    }
    mysql_free_result(res);
    }

    ResponderExcluir