如何在我的查询中使用nextval?

时间:2014-09-15 17:49:43

标签: c# oledbcommand

  • 显示以下错误:ORA-01722:无效的数字。
  • 运行代码后
  • 查询结果:

    INSERT INTO USUARIOS (ID,MATRICULA,NOME,SENHA,NIVEL,MALETA,EMAIL) 
    VALUES ('select id_usuarios.NEXTVAL from dual','TESTE','Frederico','TESTE','1','7000','daerro@erro.com.br')
    

protected void btn_incluir_Click(object sender,EventArgs e)         {

        OleDbConnection cnx = new OleDbConnection(new AdministradorDAO().conexao);
        cnx.Open();

        string seq = ("select id_usuarios.NEXTVAL from dual");
        OleDbCommand cmdo = new OleDbCommand(seq, cnx);
        cmdo.ExecuteNonQuery();

        //string sqltxt = "INSERT INTO USUARIOS (ID,MATRICULA,NOME,SENHA,NIVEL,MALETA,EMAIL) VALUES (ID_USUARIOS.NextVal,'MATRICULA','NOME','SENHA','NIVEL',MALETA,'EMAIL')";


        string sqltxt = string.Format(
@"INSERT INTO USUARIOS ( ID
      , MATRICULA
      , NOME
      , SENHA
      , NIVEL
      , MALETA
      , EMAIL
  ) VALUES ( '{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}')"
            , seq, txt_matricula.Text, txt_nome.Text, txt_senha.Text
            , DropDownList_nivel.Text, txt_maleta.Text, txt_email.Text);


            OleDbCommand cmd = new OleDbCommand(sqltxt, cnx);

            cmd.ExecuteNonQuery();

            txt_matricula.Text = "";
            txt_nome.Text = "";
            txt_senha.Text = "";
            DropDownList_nivel.Text = "";
            txt_maleta.Text = "";
            txt_email.Text = "";
            carregaUsuarios();            

    }

3 个答案:

答案 0 :(得分:1)

首先,以下陈述将引发错误。

INSERT INTO USUARIOS (ID
        , MATRICULA
        , NOME
        , SENHA
        , NIVEL
        , MALETA
        , EMAIL
    ) VALUES ( 'select id_usuarios.NEXTVAL from dual'
        , 'TESTE'
        , 'Frederico'
        , 'TESTE'
        , '1'
        , '7000'
        , 'daerro@erro.com.br'
    )

此insert语句中的主要错误是您尝试将字符串插入到数字字段中。 ID作为整数永远不会接受'select id_usuarios.NEXTVAL FROM dual',因为您实际上尝试将'select id_usuarios.NEXTVAL FROM dual'作为实际值插入。

如果您希望将序列下一个值插入ID字段,请尝试以下操作:

INSERT INTO USUARIOS (ID
        , MATRICULA
        , NOME
        , SENHA
        , NIVEL
        , MALETA
        , EMAIL
    ) ( SELECT id_usuarios.NEXTVAL 
                , 'TESTE'
                , 'Frederico'
                , 'TESTE'
                , 1
                , 7000
                , 'daerro@erro.com.br'
            FROM DUAL
    )

二。您的NIVELMALETA字段似乎也都是数字,因此请删除撇号!

第三,最好让Oracle自己处理它的序列。使用Oracle的自动增量字段的最佳实践是编写trigger on insert,它将实际选择下一个序列值并将其放在它所属的位置。另外,请注意,如果要插入所选值,则必须使用INSERT SELECT statemement,而不是INSERT VALUE语句。

第四,使用string.Format方法确实非常非常好,因为它会为SQL Injection留出空间。相反,使用必须使用命令参数。除此之外,请尝试使用Using Blocks,因为当超出范围时,他们将处置任何不再需要的资源。

using (var cnx = new OleDbConnection(connectionString)) {
    var sql = 
@"insert into usuarios(matricula, nome, sehna, nivel, maleta, email) 
      values (@matricula, @nome, @sehna, @nivel, @maleta, @email)";

    using (var cmd = new OleDbCommand(sql, cnx)) {
        cnx.Open();

        cmd.Parameters.AddWithValue("@matricula", txt_matricula.Text);
        cmd.Parameters.AddWithValue("@nome", txt_nome.Text);
        cmd.Parameters.AddWithValue("@sehna", txt_senha.Text);
        cmd.Parameters.AddWithValue("@nivel", int.Parse(DropDownList_nivel.Text));
        cmd.Parameters.AddWithValue("@maleta", int.Parse(txt_maleta.Text));
        cmd.Parameters.AddWithValue("@email", txt_email.Text);

        try { cmd.ExecuteNonQuery(); }
        catch { }
        finally { if(cnx.State == ConnectionState.Open) cnx.Close(); }
    }
}

第五,为工作调用正确的方法很重要。

<强> DbCommand.ExecuteNonQuery

仅用于DELETEINSERTUPDATE语句的方法。

<强> DbCommand.ExecuteReader

用于具有多行和多列的SELECT语句的方法。

<强> DbCommand.ExecuteScalar

当预期结果或唯一重要值应位于第一行的第一列时使用的方法。应忽略除第一行之外的任何其他行和列。

请参阅我对这些相关问题的回答:

修改

  

我尝试在选择之前伸出一只手来检索ID(从双重中选择id_usuarios.NEXTVAL),然后检索已通过插入的ID

以下是我如何去做。

首先,在桌面上创建触发器。

create or replace trigger increment_usuarios_id
        before insert on usuarios
        for each row
    begin
        if :new.id is null then
            select id_usuarios.nextval into :new.id from dual;
        end if;
    end;        

然后,当插入usuarios数据表时,ID列将由increment_usuarios_id触发器自动投放。

因此,现在可以在不对身份进行任何特别注意的情况下插入。

insert into usuarios (
        matricula
        , nome
        , sehna
        , nivel
        , maleta
        , email
    ) values (
        'TESTE'
        , 'Frederico'
        , 'TESTE'
        , 1
        , 7000
        , 'daerror@error.com.br'
    );

commit;

然后,您将按预期看到新用户进入表格。如果这样可行,那么请使用相同的insert statement并将其设置为C#代码中sql变量的值,而不要忘记使用GUI中的实际控制值替换值。

答案 1 :(得分:0)

看看这个:link

         OleDbConnection cnx = new OleDbConnection(new AdministradorDAO().conexao);
         cnx.Open();

         string seq = ("select id_usuarios.NEXTVAL from dual");
         OleDbCommand cmdo = new OleDbCommand(seq, cnx);
         int id= (int)cmdo.ExecuteScalar(); 

         using (OleDbCommand cmd = cnx.CreateCommand())
         {
       // create command with placeholders
          cmd.CommandText = 
          "INSERT INTO USUARIOS"+
          "([ID], [MATRICULA],  [NOME], [SENHA], [NIVEL],[MALETA],[EMAIL]) "+
          "VALUES(@id, @ma, @no, @se, @ni,@ma,@em)";

       // add named parameters
       cmd.Parameters.AddRange(new OleDbParameter[]
       {
           new OleDbParameter("@id", id),
           new OleDbParameter("@ma", txt_matricula.Text),
           ...
       };


       cmd.ExecuteNonQuery();
  }

将OleDbCommand中的实际硬编码参数替换为占位符(前缀为@), b)将OleDbParameter的实例添加到DbCommand.Parameters属性。参数名称必须与占位符名称匹配。

答案 2 :(得分:0)

Will Marcouiller:我发现语法没有错误。

using (var cnx = new OleDbConnection(new AdministradorDAO().conexao))
{
    var sql = @"insert into usuarios(matricula, nome, senha, nivel, maleta, email) values (@matricula, @nome, @senha, @nivel, @maleta, @email)";

    using (var cmd = new OleDbCommand(sql, cnx))
    {
        cnx.Open();

        cmd.Parameters.AddWithValue("@matricula", txt_matricula.Text);
        cmd.Parameters.AddWithValue("@nome", txt_nome.Text);
        cmd.Parameters.AddWithValue("@senha", txt_senha.Text);
        cmd.Parameters.AddWithValue("@nivel", int.Parse(DropDownList_nivel.Text));
        cmd.Parameters.AddWithValue("@maleta", int.Parse(txt_maleta.Text));
        cmd.Parameters.AddWithValue("@email", txt_email.Text);

        try { cmd.ExecuteNonQuery(); }
        catch { }
        finally { if (cnx.State == ConnectionState.Open) cnx.Close(); }

    }
}