Usuário com melhor resposta
Uso de variáveis do MySQL via MySqlCommand

Pergunta
-
Bom dia a todos!
Tenho o seguinte comando (SQL) para sincronizar duas tabelas:
"insert into tabela_destino (id, campo1, campo2)
select @cod:=@cod+1 as id, campo1, campo2 from tabela_origem, (select @cod:=(select max(id) from tabela_destino)) as cod;"O comando atende perfeitamente minha necessidade, que é inserir os registros na tabela "tabela_destino" sem que tenha problemas de id duplicados, ou seja, já estou verificando o maior id e incrementando automaticamente para cada novo registro! (esse campo não é auto_increment)
Meu problema: não consigo executar esse comando utilizando o MySqlCommand, pois quando tento executar (ExecuteNonQuery()) recebo uma exceção informando que o parâmetro "@cod" não foi setado... "@cod" é uma variável que será instanciada e controlada pelo MySQL...
Alguém sabe como posso executar essa string no MySQL pela minha aplicação(C#)?
Desde já agradeço
Filipi Brentegani
Respostas
-
Por que você não faz em dois tempos? Acredito que fica um código mais bonito:
string sql = "SELECT MAX(id) FROM tabela_destino"; MySqlCommand cmd = new MySqlCommand(sql, connection); int id = int.Parse(cmd.ExecuteScalar()) + 1; sql = "INSERT INTO tabela_destino (id, campo1, campo2)" + " SELECT @newCod as id, campo1, campo2" + " FROM tabela_origem"; MySqlCommand cmd = new MySqlCommand(sql, conn); cmd.Parameters.AddWithValue("@newCod", id); cmd.ExecuteNonQuery();
Quanto a gravação concorrente é só dar uma pesquisada (Handling Data Concurrency irá trazer mais resultados), tem bastante material na internet que explica como evitar esse tipo de situação.
Ao infinito e além!
- Editado Fabio R. Luz segunda-feira, 25 de fevereiro de 2013 17:43
- Marcado como Resposta Filipi Brentegani terça-feira, 26 de fevereiro de 2013 11:30
Todas as Respostas
-
Acontece que '@' é considerado um parâmetro para o ADO.NET. Considere o seguinte SQL:
INSERT INTO tabela_destino (id, campo1, campo2) SELECT @newCod as id, campo1, campo2 FROM tabela_origem
@newCod seria uma variável, que precisa ser setada pelo MySqlCommand, exemplo:
MySqlCommand cmd = new MySqlCommand(sql); cmd.Parameters.AddWithValue("@newCod", seuNovoCodigo);
A partir daqui, @newCod terá um valor, que nesse caso será a variável: seuNovoCodigo. Esta variável pode ser, e será no seu caso, o retorno de um outro sql somando + 1.
Ao infinito e além!
-
Obrigado pela resposta Fabio!
Realmente, o MySqlCommand reconhece o o trecho "@cod" da string como um parâmetro! Mas eu preciso que aconteça o contrário, pois isso não é um parâmetro!
Usando da forma que eu havia escrito, eu consigo movimentar quantos registros existirem na tabela "tabela_origem", inserindo-os na "tabela_destino", já fazendo que o id sofra um 'auto_incremento' a partir do último id inserido na "tabela_destino"... Esse recurso que estou usando é algo parecido com CURSOR utilizado em outros SGBDs... Não sei exatamente se isso que estou fazendo é o mesmo recurso.
OBS: Vale apenas lembrar que o comando está correto, o select está retornando a informação no formato que ela deve ser inserida! O único problema é o MySqlCommand interpretar o @ como prefixo de um parâmetro!
Caso não consiga executar o comando na íntegra, terei de usar a solução que você me sugeriu, vai custar um pouco mais de código, e pensando em gravação concorrente, terei que tomar alguns outros cuidados!
Caso consiga fazer como planejei a princípio, posto a resolução aqui!
Obrigado Fabio!!!!
Filipi Brentegani
- Editado Filipi Brentegani segunda-feira, 25 de fevereiro de 2013 16:00 Informação adicional, melhora na explicação!
-
Por que você não faz em dois tempos? Acredito que fica um código mais bonito:
string sql = "SELECT MAX(id) FROM tabela_destino"; MySqlCommand cmd = new MySqlCommand(sql, connection); int id = int.Parse(cmd.ExecuteScalar()) + 1; sql = "INSERT INTO tabela_destino (id, campo1, campo2)" + " SELECT @newCod as id, campo1, campo2" + " FROM tabela_origem"; MySqlCommand cmd = new MySqlCommand(sql, conn); cmd.Parameters.AddWithValue("@newCod", id); cmd.ExecuteNonQuery();
Quanto a gravação concorrente é só dar uma pesquisada (Handling Data Concurrency irá trazer mais resultados), tem bastante material na internet que explica como evitar esse tipo de situação.
Ao infinito e além!
- Editado Fabio R. Luz segunda-feira, 25 de fevereiro de 2013 17:43
- Marcado como Resposta Filipi Brentegani terça-feira, 26 de fevereiro de 2013 11:30
-
Fabio, estava prestes a implementar algo próximo a que foi sugerido por você, quando localizei a solução para a minha dúvida:
No manual do MySQL, em "8.4. UserDefined Variables", é mostrado como utilizar variáveis no banco, e eu vi uma forma diferente de declarar e acessar as variáveis, usando o caractere aspas simples!
O comando ficou o seguinte:
"insert into tabela_destino (id, campo1, campo2)
select @'cod':=@'cod'+1 as id, campo1, campo2 from tabela_origem, (select @'cod':=(select max(id) from tabela_destino)) as cod;"Assim o MySqlCommand não interpreta as variáveis de banco como parâmetros, e eu consigo utilizar o processamento do próprio MySQL, fazendo que o processo seja mais rápido, e já garante um eventual problema de gravações concorrentes na mesma tabela!
Obrigado pela força!
Abraço