SQL syntax error when updating a record in C#

Asked

Viewed 264 times

1

When I run my program to update a record, I get the following syntax error

![erro

But my SQL syntax is correct:

string comando = "UPDATE cliente SET nome = '" + dto.Nome + "', SET email = '" + dto.Email + "' WHERE id = " + dto.Id;

Presentation layer:

namespace Projeto3Camadas
{
    public partial class frmCadastroCliente : Form
    {
        ClienteBLL bll = new ClienteBLL();
        ClienteDTO dto = new ClienteDTO();
        public frmCadastroCliente()
        {
            InitializeComponent();
        }

        private void frmCadastroCliente_Load(object sender, EventArgs e)
        {
            CarregarGrid();
        }

        //EVENTO INSERIR E ATUALIZAR
        private void btnGravar_Click(object sender, EventArgs e)
        {
            //LOGICA QUE SE O ID DO CLIENTE FOR VAZIA, EFETUA A OPERAÇÃO DE INSERIR, SE NÃO EFETUA A AÇÃO DE ATUALIZAR
            dto.Nome = txtNome.Text;
            dto.Email = txtEmail.Text;

            if (txtId.Text == "")
            {
                bll.Inserir(dto);
            }
            else
            {
                dto.Id = int.Parse(txtId.Text);
                bll.Atualizar(dto);
            }

            CarregarGrid();
        }

        //CRIANDO UM METODO ESPESSIFICO PARA CARREGAR O GRID
        private void CarregarGrid()
        {
            gridClientes.DataSource = bll.SelecionarTodosClientes();
        }

        //AO CLICAR EM UM DETERMINADO CLIENTE, ELE VAI SELECIONAR E MOSTRAR NOS CAMPOS NA POSIÇÃO INDICADA: 
        private void gridClientes_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            txtId.Text = gridClientes.Rows[e.RowIndex].Cells[0].Value.ToString();
            txtNome.Text = gridClientes.Rows[e.RowIndex].Cells[1].Value.ToString();
            txtEmail.Text = gridClientes.Rows[e.RowIndex].Cells[2].Value.ToString();
        }
    }
}

DAL layer:

namespace Projeto3Camadas.Code.DAL
{
    class AcessoBancoDados
    {
        //Atributos da classe Mysql
        private MySqlConnection conn;
        private DataTable data;
        private MySqlDataAdapter da;

        //Dados da conexao
        private string server = "localhost";
        private string user = "root";
        private string password = "";
        private string database = "dbclientes";

        //CONECTAR
        public void Conectar()
        {
            //Se a conexao estiver aberta, eu fecho ela antes de abrir uma nova conexão
            if (conn != null)
            {
                conn.Close();
            }
            //Guarda os dados da string de conexao
            string connStr = $"server = {server}; user = {user}; password = {password}; database = {database}; pooling = false";
            //string connStr = String.Format("server={0};user id={1}; password={2}; database={3}; pooling=false", server, user, password, database);

            //Tratamento de exceção
            try
            {
                //Concretiza o objeto conn para conexao e passa por parametro a string de conexao connStr
                conn = new MySqlConnection(connStr);
                conn.Open();
            }
            catch (MySqlException ex)
            {

                throw new Exception(ex.Message);
            }
        }       

        //EXECUTAR COMANDO SQL
        public void ExecutarcomandoSql(string comandoSql)
        {
            //Executa o comando passando por parametro a string digitada no comando sql
            MySqlCommand comando = new MySqlCommand(comandoSql, conn);
            comando.ExecuteNonQuery();
            conn.Close();
        }

        //EXECUTAR LEITURA PREENCHE A TABALE E RETORNAR
        public DataTable RetDataTable(string sql)
        {
            //Retorno de um objeto Aqui so pode comando select
            //Concretisa o objeto data e da, em da é passado o sql e a conexao
            data = new DataTable();
            da = new MySqlDataAdapter(sql, conn);
            //Preenche o objeto "da" com os daddos que estao no datatable "data"
            da.Fill(data);
            //Retorna o objeto "data" já preenchido
            return data;
        }

        //EXECUTAR E RETORNAR OS DADOS SELECIONADOS
        public MySqlDataReader RetDataReader(string sql)
        {
            //Retorna o objeto "MySqlDataReader" dado de um comando SELCET
            //concretisa a criação do objeto "comando"
            MySqlCommand comando = new MySqlCommand(sql, conn);
            //Objeto comando criado, basta executa-lo de modeo que ele retorne um objeto do tipo MySqlDataReader
            MySqlDataReader dr = comando.ExecuteReader();
            //Retorna o objeto dr ja preenchido
            return dr;
        }
    }
}

DTO layer:

namespace Projeto3Camadas.Code.DTO
{
    class ClienteDTO
    {
        private int id;
        private string nome;
        private string email;

        public int Id { get => id; set => id = value; }
        public string Nome { get => nome; set => nome = value; }
        public string Email { get => email; set => email = value; }
    }
}

Layer BLL:

namespace Projeto3Camadas.Code.BLL
{
    class ClienteBLL
    {

        AcessoBancoDados bd = new AcessoBancoDados();

        public void Inserir(ClienteDTO dto)
        {
            //tratamento de erro para passar uma mensagem elegante para o usuario de modo que ele tenha ao menos a possibilidade de tentar resolver o erro ou ate mesmo ajudar o suporte a desvendafr o possivel errro 
            try
            {
                //Tratando de um possivel erro do usuario passar um nome com o uso de uma apostrofe ' pois o banco de dados pode confundir 
                string nome = dto.Nome.Replace("'", "''");
                //concretizando a instanciação do objeto, pois esse processo e matado no finally, sendo assim ao cadastrar dois usuarios ou mais simultaneamente, enfrentariamos um erro de objeto nao encontrado ou nao instanciado
                bd = new AcessoBancoDados();
                bd.Conectar();
                string comando = "INSERT INTO cliente(nome, email) VALUES('" + nome + "', '" + dto.Email + "')";
                bd.ExecutarcomandoSql(comando);
            }
            catch (Exception ex)//essa variavel recebe detalhes do erro 
            {
                //nesse caso irá aparecer para o usuario um mensagem mais elegante e descritiva sobre o erro, seguida dos detalhes tecnicos.
                throw new Exception( "Erro ao tentar inserir um usuario: DECRIÇÃO DO ERRO => " + ex.Message);
            }
            //Esse bloco sempre sera executado, dando ou nao dando erro.
            finally
            {
                //nesse caso e bem espessifico o seu uso, pois vai depender de cada aplicão, nesse caso estamos matando o processo do objeto db
                //um detalhe e que ao inserir um novo usuario de forma simuntanea, enfrentaremos um novo erro, pois o objeto bd nao esta instanciado.
                //SOLUÇÃO   - INSTANCIAR DENTRO DO BLOCO CACTH CONCRETIZANDO
                bd = null;
            } 
        }

        public void Atualizar(ClienteDTO dto)
        {
            try
            {
                string nome = dto.Nome.Replace("'", "''");
                bd = new AcessoBancoDados();
                bd.Conectar();
                string comando = "UPDATE cliente SET nome = '" + dto.Nome + "', SET email = '" + dto.Email + "' WHERE id = " + dto.Id;
                bd.ExecutarcomandoSql(comando);
            }
            catch (MySqlException ex)
            { 
                throw new Exception("Erro ao tentar gravar usuario na banco de dados. DETALHES TECNICOS => " + ex.Message);
            }
            finally
            {
                bd = null;
            }
        }
        public DataTable SelecionarTodosClientes()
        {
            DataTable dt = new DataTable();
            try
            {
                bd = new AcessoBancoDados();

                bd.Conectar();
                dt = bd.RetDataTable("SELECT * FROM cliente ORDER BY id DESC");
            }
            catch (Exception ex )
            {

                throw new Exception("Ero ao selecionar os usuarios no banco de dados. DETALHES TECNICO DO ERRO:" + ex.Message);
            }
            finally
            {

            }
            return dt;
        }

    }
}

2 answers

7

Your code has some problems, even if it works, it’s wrong. I won’t talk about them all in detail.

The wrong use exceptions, I only advise researching the subject right here on the site to start doing right, you are making the existing exceptions worse.

Also research on the use of int.Parse(txtId.Text), this along with wrong exception will be a huge problem because a user typing error will turn into an SQL error. Search here how to solve this.

That class AcessoBancoDados should implement IDisposable to not create problems, if you don’t understand how to do this don’t create a class like this, the code will be extremely vulnerable to failures. So if you don’t fix this, you’d better write the database access code in your own code. Never use things you don’t know the consequences of.

But the greatest vulnerability lies in the rather wrong use of mounting a query, allowing SQL Injection attacks in a very easy way. Using the right pattern in C# makes it harder to err in SQL as well:

using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand("UPDATE cliente SET nome = @nome, email = @email WHERE id = @id;", connection) {
    command.Parameters.Add("@id", SqlDbType.Int);
    command.Parameters["@id"].Value = dto.Id;
    command.Parameters.AddWithValue("@nome", dto.Nome);
    command.Parameters.AddWithValue("@email", dto.Email);
    connection.Open();
    command.ExecuteNonQuery();
}

I put in the Github for future reference.

I took the catch of exception because to do nothing useful it is better not to capture.

Under no circumstances continue using SQL in the way you did in the code! If you continue programming the way you did, you will not have problems by coincidence.

  • Thank you very much for the guidance, and I am a beginner, I am not a programmer yet, this logic used and a course that I am following with my studies. I hope you will guide me better in the next modules.

  • I suggest you drop this course, really, it will hurt you.

  • You could recommend me some, in which I don’t come investing wrong, I’ve bought some online and regretted it too. I am accepting indications of good content, the bad have already found alone. I don’t want to spend and sacrifice my time to learn wrong.

  • No, I can’t recommend it, because I look for ways to learn structures, this business of learning on demand, taking an online course doesn’t work, almost all deception, even if it’s not the intention of the person. I’m sure it’s good, but I don’t know them. People waste time because they want to cut corners, make the complex before they learn the basics, it’s the economy that’s so expensive.

  • And what I could be doing, reading the technical documentation I read more I don’t quite understand yet. The college doesn’t actually teach programming, it has a lot of cheap and expensive books, but I don’t have recommendations where you can tell me that helps you. Could you give me a hand?

  • It starts with the basics, learning to program before learning technology, before reading documentation, even to understand documentation, and to be able to create critical spirit to what you see, because even documentation isn’t there to show you how to do it, is there only to exemplify the specific mechanism, and as many people do not have it copies all wrong. I’ll post a post one day about it, but only when I have time to do something well thought out, because opinion all over again, I need something that’s well thought out.

Show 1 more comment

1


The SQL command is wrong when we use UPDATE, SET appears only once, and the fields and values you are changing are separated by a comma.

string comando = "UPDATE cliente SET nome = '" + dto.Nome + "', SET email = '" + dto.Email + "' WHERE id = " + dto.Id;

This command only needs one SET, only remove the second before the email field:

string comando = "UPDATE cliente SET nome = '" + dto.Nome + "', email = '" + dto.Email + "' WHERE id = " + dto.Id;

This syntax is valid for any database, but here the Mysql documentation: Mysql update

Browser other questions tagged

You are not signed in. Login or sign up in order to post.