1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

VB.net / SQL Server

Discussão em 'Programação' iniciada por diog0silva, 27 de Março de 2009. (Respostas: 38; Visualizações: 3200)

  1. diog0silva

    diog0silva Power Member

    Boas.

    Tenho uma dúvida. Tenho um campo numa tabela que é NUMERIC (3,1). Ou seja aceita valores 30,1 ou 45,7, etc.

    Acontece que quando tou a inserir um valor nesse campo através do Visual Basic, ele dá-me sempre erro.

    ja tentei

    INSERT INTO tabela (cod_produto, preco) VALUES (20, 12.1)
    INSERT INTO tabela (cod_produto, preco) VALUES (20, 12,1)
    INSERT INTO tabela (cod_produto, preco) VALUES (20, '12.1')
    INSERT INTO tabela (cod_produto, preco) VALUES (20, '12,1')

    Dá sempre erro. Quando não meto as pelicas e meto a virgula ele assume três campos. Quando não meto as pelicas e meto o ponto, ele ignora o ponto (121).

    Isto quando insiro através do VB!

    Cumprimentos.

    EDIT: Já consegui.

    Se alguém tiver a mesma duvida terá que usar a função replace. Ou seja, se o valor do preço tiver no campo txtPreco.text, e o código do produto no campo txtCod.text, ficará assim:

    "INSERT INTO tabela VALUES (" & txtCod.text & "," & replace(Cdbl(txtPreco.text), ",", ".") & ");"
     
    Última edição: 27 de Março de 2009
  2. jpaulino

    jpaulino Power Member

  3. AndreVSerafim

    AndreVSerafim Power Member

    Penso que o Trim() faz isso tambem ;)
     
  4. ribeiro55

    ribeiro55 Power Member

    O Trim apenas te come os "leading spaces", de uma String.

    Acho que nem precisavas do replace. Não testei, mas acho que se enviares um double para um campo numeric, é papado.
    Enfim, já resolveste e isso é que interessa ;)
     
  5. diog0silva

    diog0silva Power Member

    JPaulino, tive a dar uma vista de olhos nesses links e vao-me ser muito uteis. Porém, não falam de uma coisa que eu preciso de fazer.

    Tipo, quero criar um formulário (com textbox's e não com datagridview) que vá buscar os dados a uma determinada tabela. E queria programar botoes para percorrer os vários registos (tipo anterior, seguinte, procurar).

    Conheces algum outro link que possas aconselhar? Se for do genero deste, é optimo, porque está tudo mesmo bem explicado.

    Obrigado pela vossa ajuda.
     
  6. PNDmartins

    PNDmartins Power Member

    Vou aproveitar este post e fazer uma pergunta que me anda a incomodar a algum tempo.

    Porque tanta obsessão com os SqlParameters?
     
  7. jpaulino

    jpaulino Power Member

    Podes utilizar um BindingNavigator. Estes são alguns artigo mas existem bastantes se procurares por BindingNavigator.

    http://www.developer.com/net/vb/article.php/3558771
    http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingnavigator.aspx
    http://msdn.microsoft.com/en-us/library/3y4w3c32(VS.85).aspx



    Os SqlParameters ou OleDbParameters não são propriamente uma obsessão mas sim uma facilidade para o programador. Eles evitam e resolvem diversos problemas que se tem durante o desenvolvimento. Alguns exemplos de vantagens:

    Organização
    É mais fácil construir um comando T-SQL do que concatenar uma string, mesmo usando um StringBuilder ou o String.Format(). Por exemplo:

    "INSERT INTO myTable (id,nome,morada,localidade,codpostal) VALUES (@id,@nome,@morada,@localidade,@codpostal)"

    E depois é só definir os parameters linha a linha do que fazer:

    "INSERT INTO myTable (id,nome,morada,localidade,codpostal) VALUES (" & Me.TextBox1.Text ",'" & Me.TextBox2.Text & "','" & Me.TextBox3.Text & "','" Me.TextBox4.Text & "'," & Me.TextBox5.Text & ")"

    Agora imagina se são 30 ou 40 campos a inserir.

    Evitar Erros
    Usando os parameters apenas necessitamos de indicar o tipo de dados e o parameter, não sendo necessário conversões, substituições, etc.

    Por exemplo numa data temos de especificar o formato correcto, nos números tempos de verificar se é virgulas ou pontos, num nome do tipo O'brien temos de substituir a ' por ", etc. Agora imagina que mudas de país ... a formatação é diferente e tens de recorrer ao namespace Globalization para acertar tudo.

    Um conjunto de operações que não são necessárias usando parameters.

    Segurança
    Os parameters, em conjunto com os stored procedures, evitam os SQL Injections que são umas das principais causas de segurança em aplicações web. Podes ler um artigo que escrevi e onde tem um video que mostra como é simples fazer um ataque em aplicações não seguras:

    Artigo: VB.NET: Utilizando Stored Procedures



    São alguns exemplos das vantagens de utilizarmos parameters.
     
  8. diog0silva

    diog0silva Power Member

    jpaulino, há alguma maneira de ver o código que está nos bindingnavigators? é que não gosto muito deles, mas queria por um botão "anterior" e "seguinte".

    E já agora, se puderes, explica-me para que serve esta parte do código do link que deste (parte 1):

    Dim x As Integer = command.ExecuteNonQuery()
    If x < 1 Then
    MsgBox("A operação efectuada não retomou qualquer resultado.")
    End if

    E já agora se me puderes explicar a diferença entre ExecuteScalar e ExecuteNonQuery lol
     
    Última edição: 28 de Março de 2009
  9. jpaulino

    jpaulino Power Member

    O BindingNavigator é uma maneira simples de navegar nos registos e usa uma BindingSource. Podes utilizar uma BindingSource apenas e não precisas daqueles botões

    http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.movenext.aspx

    O que está a fazer é executar um comando transact SQL (Insert, Delete ou Update) e verifica o número de registos que foi afectado. Depois verifica o resultado e mostra uma mensagem a indicar que não inseriu, não apagou ou não actualizou. Só isso!

    O ExecuteScalar retorna um resultado e é útil para ler informação de um só campo, como por exemplo um total de registos que está na base de dados. Um ExecuteNonQuery executa um comando e devolve o número de registos afectados.
     
  10. diog0silva

    diog0silva Power Member

    Obrigadão! =)

    Já agora, já vi que percebes muito do assunto, queria por-te mais uma questão.

    Tou a usar Parameters como recomendaste. E tipo, eu tenho um form com vários campos que correspondem aos vários campos da tabela. Mas nem todos são de preenchimento obrigatório.

    Imagina que tenho os campos cliente_cod, cliente_nome, cliente_contacto, cliente_tipo (em que só código e nome do cliente são obrigatórios de preecher, e que o tipo só pode ser "Bom" ou "Mau").

    Se eu no form só preencher o campo código e nome, dá erro, porque ele assume que os outros campos têm valor " ". Ou seja, o contacto só aceita valores numericos, e o erro que ele dá é que não consegue converter " " para Integer. Quanto ao tipo, diz que tou a violar uma regra, já que só posso por ou "Bom" ou "Mau".

    Tens alguma ideia de como possa resolver isto?

    Obrigado mais uma vez.

    EDIT:

    Eu sei uma maneira, mas além de muito trabalhosa, escrevo mil linha de codigo lol

    Do genero, eu tou a fazer:

    INSERT INTO cliente VALUES (@cod_cliente, @nome_cliente, @contacto_cliente, @tipo_cliente)

    cmd.Parameters.Add... Value = txtCodCliente.text
    cmd... Value = txtNomeCliente.text
    ...

    Ou seja, ponho todos os campos. Claro que posso por um IF, e se os campos X ou Y forem igual a " ", faço um INSERT diferente só com os campos que não são iguais a " ".

    Mas além desta solução, nao conheces outra mais prática?
     
    Última edição: 28 de Março de 2009
  11. ribeiro55

    ribeiro55 Power Member

    Validação de campos, SEMPRE.
    O que vai para a base de dados já tem de ir formatado.
    Bindingnavs são bons para complicar processos que são já de si bastante simples.
    Quando queres abanar um pouco a fórmula está o caldo entornado.
    Faz me lembrar aquilo que um hardcore user de W98 sente ao sentar-se à frente de um WVista. Sente uma brutal perda de controlo sobre o que está a fazer. Chega a ser frustrante.
    Um freshman, com o vista não aprende squat. Quase que se faz perder a noção de ficheiro.
    Na minha opinião há que fazer um pequeno esforço por entender as operações básicas.
    Acabam por fazer as coisas e ficar a saber o mesmo, o que não é bom.
    E olha que há bons exemplos, não só no forum mas também aí no blog do jpaulino.
    Boas explicações sim senhor :)
     
  12. diog0silva

    diog0silva Power Member

    Então como é que faço para que cada vez que uma textbox não seja preenchida ele assuma que o valor da mesma é NULL e não " " ?
     
  13. jpaulino

    jpaulino Power Member

    É como o ribeiro55 já disse, é sempre necessário fazer validações e é muito importante ir lendo BEM as informações que vão sendo dadas. Não se pode simplesmente fazer por fazer, é preciso entender como as coisas funcionam

    Só tens de verificar se o campo está em branco e fazer isto:

    Código:
     
    If Me.TextBox1.Text = String.Empty Then
         cmd.Parameters(..). Value = DbNull.Value
    Else
         cmd.Parameters(..). Value = Me.TextBox1.Text 
    End If
    
     
  14. diog0silva

    diog0silva Power Member

    Obrigado jpaulino, resultou =)

    Mas tenho outra dúvida. O form para inserir registos já está a funcionar na perfeição. O problema agora é ler registos, fazer seguinte, anterior, procurar, etc. Tive a ler o teu blogue e tive-me a guiar por lá, mas o exemplo que está lá não lê os dados da base de dados para textbox's, que era o que eu queria fazer.

    Até agora, tenho o código assim:

    Const constr As String = "Data Source....."
    Dim db As New SqlConnection(constr)

    db.Open()

    Dim varsql As String
    varsql = "SELECT * FROM tab_cliente ORDER BY clt_nome"

    Dim cmd As New SqlCommand (varsql, db)
    Dim reader As SqlDataReader

    reader = cmd.ExecuteReader
    reader.Read()

    txtCodCliente = reader.Item("clt_cod")
    txtNomeCliente = reader.Item("clt_nome")
    txtClienteTipo = reader.Item("clt_tipo")
    ...

    db.Close()

    De facto, consigo ler no form os dados do registo do primeiro cliente. Agora, gostava de saber se é esta a maneira correcta de fazer a leitura da base de dados, e se sim, como programo os botões anterior e seguinte?

    EDIT: desta maneira tem uma falha; se o campo for NULL, ele bloqueia lol
     
    Última edição: 29 de Março de 2009
  15. diog0silva

    diog0silva Power Member

    Preciso mesmo da vossa ajuda lol
     
  16. PNDmartins

    PNDmartins Power Member

    Obrigado jpaulino. Já conhecia as stored procedures e tudo o resto, so me escapava a noção do SqlInjection e da globalização. Agora sim entendo o porque de usar os parametros mesmo sem usar stored procedures.

    Diog0Silva, nesse formulário onde estás a ler os dados, apenas faz isso certo? ler os dados e + nada?
     
  17. diog0silva

    diog0silva Power Member

    Sim. Aquele código que pus aqui le os dados do primeiro registo da tabela. Esse form só vai servir para ler os dados, fazer seguinte, anterior, fazer procuras, alterar e apagar dados.

    Apagar e alterar eu acho que consigo. Ler, navegar entre os registos e procurar um registo é que está mais complicado.

    Tenho procurado em vários sites e livros, mas os exemplos que aparecem são com console application.
     
  18. PNDmartins

    PNDmartins Power Member

    Eu ia-te a sugerir para usares uma DataTable em vez de um DataReader mas para o que queres sei que a formas mais simples, apesar de não conseguires ter tanto controlo como com a DataTable.

    Basicamente quando usas uma datatable ficas com uma tabela tal e qual como está no sql em memoria que podes usar para mostrar dados mas sempre que fizeres alguma alteração a tabela, tens que passar essa alteração para o Sql.

    Um exemplo de como meter os dados numa Datatable:

    Código:
    [COLOR="YellowGreen"]'Este exemplo assume que tens uma variavel do tipo SqlConnection chamada SqlCon com os 
    'dados da ligação a base de dados[/COLOR]
    Dim SqlCmd as new SqlCommand("Select * from TabelaXpto", SqlCon)
    Dim SqlAdp As New SqlDataAdapter(SqlCmd)
    
    Dim Dt As New DataTable
    
    SqlAdp.Fill(Dt)
    
    Depois podes navegar os dados internamente. Para colocar dados numa textbox:

    Código:
    Textbox1.Text = Dt.Rows(0).Item("Coluna1").ToString
    Textbox2.Text = Dt.Rows(0).Item("Coluna2").ToString
    
    No exemplo, tens que ter em atenção o .rows(0) onde o 0 é o numero da linha (Atenção que é zero-based index, ou seja o index começa no 0 em vez de começar no 1) e o .Item("Coluna1") que é a coluna de onde queres retirar os dados. Também podes colocar .Item(0) que devolve-te os dados da primeira coluna mas convem usares sempre os nomes.

    Quando queres alterar ou eliminar dados, tens que executar a query para o mesmo no Sql, e depois ir buscar novamente a tabela para actualizares os dados.
     
  19. diog0silva

    diog0silva Power Member

    Obrigado PNDmartins, funciona dessa maneira!

    Diz-me só uma coisa: alguma razão em especial para se usar o ToString?

    EDIT: ya, acho q já percebi a utilidade do ToString lol se não converter para string, ele bloqueia se existirem campos NULL.

    Já agora, ponho nova questão lol

    Não consigo eliminar "clientes", porque têm "compras" efectuadas. Ou seja, quero eliminar um registo numa tabela, mas como esse registo está a ser utilizado noutra tabela ele não deixa. Alguma solução? É mesmo para apagar o registo e todas as suas incidências noutras tabelas.
     
    Última edição: 30 de Março de 2009
  20. PNDmartins

    PNDmartins Power Member

    Apenas para ter a certeza de que os valores que vêem da dase de dados são convertidos para string para dar ao texto da textbox, visto que a mesma é do tipo string.

    Eu programo com a opção "OptionStrick" ligada, o que me obriga a ter sempre os valores convertidos das maneiras correctas, para minimizar os erros não vá eu enganar-me quando estou a programar e querer colocar por exemplo:

    Código:
    Dim AData as Date = "Omg, este é o tipo errado e o programa vai arrebentar."
    
    Dai habituei-me a converter sempre os dados para os tipos correctos. Não necessitas colocar o .tostring mas é uma mais valia.

    Também é um bom habito converter sempre os dados para os tipos correctos.

    EDIT: Tinha-me esquecido dos valores nullos como desde a um tempo para cá ando a habituar-me a utilizar o .tostring, mas sim, também evita isso.
     
    Última edição: 30 de Março de 2009

Partilhar esta Página