How to use multiple SQL commands (in the case delete on ORACLE) in one line only on C#?

Asked

Viewed 2,949 times

6

I made a command because of Foreign Keys, only to plug hole, but it is not working for an invalid character error, I believe it is the ";".

I know I’m doing this the wrong way, so I accept suggestions for more appropriate code. At first I just need to make it work, because it’s just a demonstration of the application.

Follows the code:

    public string ExcluirIndicador(int codigo)
    {
        try
        {
            comand = connectionFactory.CreateCommand();
            comand.CommandText = "DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_CR_INDICADOR_PERIODO WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_INDICADOR WHERE COD_INDICADOR = " + codigo + "";
            comand.Connection = connection;
            comand.ExecuteReader();

            return "Sucesso";
        }
        catch (Exception e)
        {
            var erro = e.Message;
            return "Erro";
        }
    }

The mistake:

ORA-00911: invalid character\n
  • Debug to know exactly the error, is the code coming correctly? Here I ran a command with more than one delete and it worked normal.

  • The default of your project is to build SQL queries in C# and only run in the bank or you can have a database process that runs only in c#?

7 answers

6

Try to put the querys inside an Anonymous Blocks BEGIN..END

What are Anonymous Blocks?

  • They are declared in an application at the place where they are to be executed and passed in run-time at the PL/SQL interpreter, are usually built dynamically and executed only once.

Example

BEGIN DELETE FROM; DELETE FROM...; DELETE FROM...; END; 
    public string ExcluirIndicador(int codigo)
    {
        try
        {
            comand = connectionFactory.CreateCommand();
            comand.CommandText = "BEGIN DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_CR_INDICADOR_PERIODO WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_INDICADOR WHERE COD_INDICADOR = " + codigo + " END";
            comand.Connection = connection;
            comand.ExecuteReader();

            return "Sucesso";
        }
        catch (Exception e)
        {
            var erro = e.Message;
            return "Erro";
        }
    }
  • Can you put an explanation, however quick? Simply saying "Do this" leaves the answer half-empty. Try to explain why this is a solution, what the purpose, or what the "secret" of why it works.

2

A more robust solution and complete what I suggest. Knowing that everything has a quick, easy and wrong solution, better waste time on implementation for quality gain!

#region Controle de Transação
using (OracleConnection connection = new OracleConnection(ConfigurationManager.ConnectionStrings["Oracle"].ConnectionString))
using (OracleCommand command = connection.CreateCommand())
{
                try
                {
                    connection.Open();

                    using (var transaction = connection.BeginTransaction())
                    {
                        #region excluindo registro da tabela 1'
                        command.CommandText = Constantes.sql1; //Constantes é uma classe estatica com declarações de variaveis ou constantes estaticas onde centraliza os scripts.
                        command.CommandType = System.Data.CommandType.Text;
                        command.Parameters.Add(new OracleParameter("p_codigo ", OracleDbType.int, ParameterDirection.Input)).Value = codigo;
                        command.ExecuteNonQuery();
                        command.Parameters.Clear();
                        #endregion

                        #region excluindo registro da tabela 2'
                        command.CommandText = Constantes.sql2;
                        command.CommandType = System.Data.CommandType.Text;
                        command.Parameters.Add(new OracleParameter("p_Numreq", OracleDbType.int, ParameterDirection.Input)).Value = codigo;
                        command.ExecuteNonQuery();
                        command.Parameters.Clear();
                        #endregion

                        #region excluindo registro da tabela n'
                        command.CommandText = Constantes.sql3;
                        command.CommandType = System.Data.CommandType.Text;
                        command.Parameters.Add(new OracleParameter("p_Numreq", OracleDbType.int, ParameterDirection.Input)).Value = codigo;
                        command.ExecuteNonQuery();
                        command.Parameters.Clear();
                        #endregion

                        transaction.Commit();
                    }
                    #endregion
                }
                //Nestes casos não devolve o requisitorio então não deve atualizar a situação do mesmo!
                catch (OracleException oe) 
                {
                    var retornoAmigavel = Constantes.Error;
                    switch (oe.ErrorCode)
                    {
                        case 12170:
                            retornoAmigavel = oe.ErrorCode +"-"+ Constantes.SemConexao;
                            break;

                        case 28000:
                            retornoAmigavel = oe.ErrorCode + "-" + Constantes.ContaBloqueada;
                            break;

                        case 1073:
                            retornoAmigavel = oe.ErrorCode + "-" + Constantes.ErroDeConexao;
                            break;

                        case 1:
                            retornoAmigavel = oe.ErrorCode + "-" + Constantes.ChavePrimariaViolada;
                            break;

                        default:
                            retornoAmigavel = Constantes.ErroGenerico + oe.Message;
                            break;
                    }
                    Console.WriteLine(retornoAmigavel, oe);
                }
                catch (Exception e)
                {
                    var EretornoAmigavel = "ERROR REQ.Nº: " + requ.numero;
                    EretornoAmigavel += "\nConstantes.ErroGenerico " + e.Message;
                    Console.WriteLine(EretornoAmigavel);
                }
            }
            #endregion

That’s it! I hope I contributed...

2

Below is a suggested improvement for your project, save the querys in a separate class in case you need to reuse elsewhere, if you need to delete a TB_INDICADOR using another parameter, you can use methods overload.

public string ExcluirIndicador(int codigo)
{
    try
    {
        comand = connectionFactory.CreateCommand();
        comand.CommandText = "BEGIN "+QueryFactory.Exclui_TB_CR_Indicador(codigo) + 
                             QueryFactory.Exclui_TB_CR_Indicador_Periodo(codigo) + 
                             QueryFactory.Exclui_TB_INDICADOR(codigo) + " END;";

        comand.Connection = connection;
        comand.ExecuteReader();

        return "Sucesso";
    }
    catch (Exception e)
    {
        var erro = e.Message;
        return "Erro";
    }
}

public static class QueryFactory
{
    public static string Exclui_TB_CR_Indicador(int codigo)
    {
        return "DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR = " +codigo+ ";  ";
    }

    public static string Exclui_TB_CR_Indicador_Periodo(int codigo)
    {
        return "DELETE FROM TB_CR_INDICADOR_PERIODO WHERE COD_INDICADOR = " +codigo +"; ";
    }

    public static string Exclui_TB_INDICADOR (int codigo)
    {
        return "DELETE FROM TB_INDICADOR WHERE COD_INDICADOR = " +codigo+"; ";
    }

}
  • Nice idea. I removed "()" from Queryfactory, but still generated error: ORA-00933: SQL command not properly ended n

  • @Joaopaulo , I edited the reply, could you check now please? thanks.

  • Thank you very much for trying. It still carries an error: "ORA-06550: line 1, column 181: nPLS-00103: Encountered the Symbol "end-of-file" when expecting one of the following: n n ; <an Identifier> <a double-quoted delimited-Identifier> nThe Symbol ";" was substituted for "end-of-file" to continue. n"

1

Try something like that:

string script = "DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_CR_INDICADOR_PERIODO WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_INDICADOR WHERE COD_INDICADOR = " + codigo + "";    
Server server = new Server(connection);
server.ConnectionContext.ExecuteNonQuery(script);

1

UPDATE*

Why You Don’t Run Individual Commands?

public string ExcluirIndicador(int codigo)
{
    try
    {
        comand = connectionFactory.CreateCommand();
        comand.Connection = connection; 

        comand.CommandType = System.Data.CommandType.Text;
        comand.CommandText = string.Concat("DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR = @codigo;",
                                           "DELETE FROM TB_CR_INDICADOR_PERIODO WHERE COD_INDICADOR = @codigo;",
                                           "DELETE FROM TB_INDICADOR WHERE COD_INDICADOR = @codigo;");
        comand.Parameters.AddWithValue("@codigo", codigo);
        comand.ExecuteReader();

        return "Sucesso";
    }
    catch (Exception e)
    {
        var erro = e.Message;
        return "Erro";
    }
}


Caution when concatenating parameters directly into commandText

If the code can be manipulated by the client, the application is vulnerable to SQL Injection.

Observing

If your command has the ExecuteScalar() or ExecuteNonQuery() prefer to use them.

  • ExecuteReader() - for more than 1 record/column
  • ExecuteScalar() - 1 single record and column
  • ExecuteNonQuery()- no return, just execution
  • Very good use explanation, but it didn’t work. When debugging when entering Executenonquery() it changes the screen of the visual studio pro browser and nothing happens. I can not give F10 to follow because he understands that this running.

  • The connection is open?

  • I think so, because when you’re not I can debug it and check it out. But debugging is not accusing any error, just keeps running eternally the Executenonquery().

  • I made a change to run the 3 together and passing the parameter more securely, you have already tried to run with the Laerte response?

  • Your change needs some reference that I did not find out what it is. Laerte’s answer returned this error: "ORA-06550: line 1, column 176: nPL/SQL: ORA-00933: SQL command not properly ended Nora-06550: line 1, column 125: nPL/SQL: SQL Statement Ignored Nora-06550: line 1, column 178: nPLS-00103: Encountered the Symbol "end-of-file" when expecting one of the: n n ; n following"

  • What’s wrong with the reference? You can post the code inspired by the Laerte answer you tested?

  • I edited his post with the code I tested.

  • Addwithvalue is generating reference error.

  • Try trading for comand.Parameters.Add(new SqlParameter { ParameterName = "@codigo", Value = codigo });

Show 4 more comments

0

I believe that for your code to work just you replace the

comand.ExecuteReader();

by the call of

comand.ExecuteNonQuery();

Because the execution of your SQL will have no return.

-2

Use the boolean OR on your Where

comand.CommandText = "DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_CR_INDICADOR_PERIODO WHERE COD_INDICADOR = " + codigo + "; DELETE FROM TB_INDICADOR WHERE COD_INDICADOR = " + codigo + "";

would simply

comand.CommandText = "DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR = " + codigo1 + " || COD_INDICADOR = " + codigo2 + "|| COD_INDICADOR = " + codigo3 + "";

I can’t remember if oracle has an in, in MS Sql would look like this:

comand.CommandText = "DELETE FROM TB_CR_INDICADOR WHERE COD_INDICADOR in (" + codigo1 + "," + codigo2 + "," + codigo3 + ")";
  • Friend, these are different tables. Disjunction will not work in this case.

  • Sorry friend, I did not read the question correctly (can I delete my answer?) In this case the answer from miaocn Carraro seems to be correct. OP reported a problem but seems to be formatting. When creating a multiline string like this one tries to use: String x = @"lines on top of each other without concatenation"

Browser other questions tagged

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