Jump to content
Fórum Script Brasil
  • 0

Inserir Tipo Binário no BD com parâmetro


Danleonhart

Question

Seguinte pessoal...

É possível inserir dados do Tipo Binário no BD com parâmetros ? :huh:

Assim eu sei que é possível:

Sub Gravar_Dados()
    Abb                       '<====== Função que abre a conexão com o BD
    Set Rs = New ADODB.Recordset
    Rs.CursorLocation = adUseServer
    Rs.Open "SELECT * FROM InDat", Con, adOpenStatic, adLockOptimistic
    
    'inclui um registro
    Rs.AddNew
   
    Rs("Nome") = txtNome.Text
    Rs("Foto") = Por_Em_Byte(camFoto) '<= Função que converte uma imagem em Bytes
    
    Rs.Update
    Set Rs = Nothing
    Con.Close
    
    MsgBox "Dados gravados !", vb script:
Agora estou tentando assim...que é com parâmetros nos campos:
Sub Inserir_Dados()
Dim Cmd As ADODB.Command
Dim Inserir As String
Dim b() As Byte

b() = Por_Em_Byte(camFoto)
Inserir = "INSERT INTO InDat(Nome,Foto)VALUES(@Nome,@Foto)"

Abb
Set Cmd = New ADODB.Command
    With Cmd
            .ActiveConnection = Con
            .Prepared = True
            .CommandText = Inserir
            .CommandType = adCmdText
            .Parameters.Append .CreateParameter("@Nome", adChar, adParamInput, , txtNome.Text)
            .Parameters.Append .CreateParameter("@Foto", adBinary, adParamInput, , b())
            .Execute
    End With
MsgBox "Dados Salvo !", vbInformation
Set Cmd = Nothing
Con.Close
End Sub

Sempre que tentei apresentou Erro: 3001

Os argumentos são incorretos, estão fora do intervalo aceitável ou estão em conflito.

e aponta para a linha: .Parameters.Append .CreateParameter("@Foto", adBinary, adParamInput, , b())

Já mudei o tipo de "adBinary" para "AdVarBinary", "adLongVarBinary" e "AdArray" mas continua sempre dando o mesmo erro... <_<

O BD é Access 2007 e o tipo do campo está como Objeto OLE.

*** EDITADO ***

Agora está dando este erro:

Erro: 3708

Objeto Parameter definido incorretamente. As informações são inconsistentes ou incompletas.

<_<

Edited by Danleonhart
Link to comment
Share on other sites

12 answers to this question

Recommended Posts

  • 0

Também não Kuroi...

Tentei inserir em uma tabela no SQL Server dessa forma, e o erro começou logo na inserção do campo "Nome"...

o erro foi esse:

Erro3.png

Nesse caso, tentei inserir apenas no campo "Nome"...

e a linha que aponta o erro é a : ".Execute".

Se coloco para inserir também com a imagem o erro volta a ser o do inicio.

Isso no SQL Server...

No Access, só o "Nome" vai normalmente...dá pró se tentar inserir a imagem...

Edited by Danleonhart
Link to comment
Share on other sites

  • 0

Se é Objeto OLE no Access, o tipo do campo tem que ser adLongVarBinary, acho que o que faltou foi passar o tamanho da imagem no quarto parâmetro.

Esse código aqui funcionou certinho no Access (são: um campo Texto de 50 posições, um campo Inteiro Longo e um campo Objeto OLE):

Option Explicit

Dim cn As New ADODB.Connection, rs As New ADODB.Recordset
Dim cm As New ADODB.Command, sql As String

Private Sub Form_Load()
    cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\x.mdb"
    cn.CursorLocation = adUseClient
    cn.Open
    
    sql = "Insert Into t (xxx, yyy, zzz) Values (@xxx, @yyy, @zzz)"
    
    Const pValor_xxx As String = "valorxy"
    Const pValor_yyy As Long = &HFF&
    
    Dim b() As Byte, tam As Long
    b = ImagemBinario(App.Path & "\pinoko02.jpg", tam)
        
    With cm
        .ActiveConnection = cn
        .CommandText = sql
        .CommandType = adCmdText
        .Parameters.Append .CreateParameter("@xxx", adVarWChar, adParamInput, 50&, pValor_xxx)
        .Parameters.Append .CreateParameter("@yyy", adInteger, adParamInput, , pValor_yyy)
        .Parameters.Append .CreateParameter("@zzz", adLongVarBinary, adParamInput, tam, b)
        
        .Execute
    End With
    
    Erase b
    
    sql = "Select * From t Where yyy = " & pValor_yyy
    Set rs = cn.Execute(sql)
    
    Set Image1.Picture = AbreImagem(rs!zzz)
End Sub
Private Sub Form_Unload(Cancel As Integer)
    If rs.State <> 0& Then
        rs.Close
    End If
    If cn.State <> 0& Then
        cn.Close
    End If
    
    Set cm = Nothing
    Set rs = Nothing
    Set cn = Nothing
End Sub[/code]
[code]Public Function ImagemBinario(ByVal file As String, Optional ByRef n As Long = 0&)
    Dim b() As Byte, f As Long
    
    f = FreeFile
    Open file For Binary Access Read As f
    
    n = LOF(f)
    If n Then
       ReDim b(1 To n) As Byte
       Get f, , b()
    End If
    
    Close f
    
    ImagemBinario = b()
End Function
Public Function AbreImagem(ByRef img As ADODB.Field) As StdPicture
    Dim b() As Byte, f As Long, file As String
    
    file = App.Path & "\kuroi.xxx"
    
    f = FreeFile
    Open file For Binary Access Write As f
    
    b() = img.Value
    Put f, , b()
    
    Close f
    Erase b
    
    Set AbreImagem = LoadPicture(file)
    Kill file
End Function

Quanto ao SQL, se o campo é varchar, deve ser adVarChar, se for char, deve ser adChar, mas não sei se isso faz muito diferença para texto.

Acho que o problema é que o modo de usar parâmetros no SQL deve ser diferente. Vejo as pessoas usando ? em vez de dar nome pros parâmetros, e depois adicionar um por um na ordem em que aparecem na query.

Ou tente setar a propriedade .NamedParameters do objeto Command como True e veja se tem algum efeito.

Não sei se imagem também é adLongVarBinary no SQL, mas pra verificar direitinho o tipo de cada campo, você pode fazer um select na tabela e verificar a propriedade rs.Fields(x).Type de cada campo no Recordset.

Edited by kuroi
Link to comment
Share on other sites

  • 0

Kuroi,

Na função ImagemBinario() a parte do script: "Optional ByRef n As Long = 0&"

isso quer dizer que "n" retorna o tamanho da foto ?! é isso :huh:

é que não costumo usar "ByVal" e "ByRef" :rolleyes:

então, a parte "ByVal file as String" é o caminho da foto...isso é necessário para a função realizar sua tarefa...

mas o "Optional ByRef n As Long = 0&" é opicional, então, se colocar algum valor nesse parâmetro ele vai influenciar em algo na função ??? porque dentro da função o "n" vai receber valor (no caso o tamanho final do arquivo).

só curiosidade...porque não sabia que função retornava mais de um valor...no caso, retornando um vetor de Bytes "b()" e o tamanho do fim do arquivo "n"...

Sai um pouco do foco por pura curiosidade :D

Estou a fazer testes com as sugestões ^_^

Obrigado pela atenção ! top.gif

Link to comment
Share on other sites

  • 0

OK !

Para o BD Access funcionou assim:

Sub Gravar_Modo_Access()
Dim Cmd As ADODB.Command
Dim Inserir As String
Dim b() As Byte
Dim tam As Long

b = Por_Em_Byte(camFoto, tam)
Inserir = "INSERT INTO InDat(Nome,Foto)VALUES(@Nome,@Foto)"

Abb
Set Cmd = New ADODB.Command
    With Cmd
            .ActiveConnection = Con
            .Prepared = True
           ' .NamedParameters = True
            .CommandText = Inserir
            .CommandType = adCmdText
            .Parameters.Append .CreateParameter("@Nome", adVarChar, adParamInput, 50, txtNome.Text)
            .Parameters.Append .CreateParameter("@Foto", adLongVarBinary, adParamInput, tam, b)
            .Execute
    End With
MsgBox "Salvo !", vbInformation
Limpar_Campos
Set Cmd = Nothing
Con.Close
End Sub
Não precisei setar o ".NamedParameters"... funcionou sem ele...só incrementei a minha função o retorno do tamanho do arquivo. Já com o SQL Serve está apresentando o seguinte erro: Erro2.png O script é esse:
Sub Gravar_Modo_SQL()
Dim Cmd As ADODB.Command
Dim Inserir As String
Dim b() As Byte
Dim tam As Long

b = Por_Em_Byte(camFoto, tam)
Inserir = "INSERT INTO InDat(Nome,Foto)VALUES(?,@foto)"

Abb
Set Cmd = New ADODB.Command
    With Cmd
            .ActiveConnection = Con
            .Prepared = True
            .NamedParameters = True
            .CommandText = Inserir
            .CommandType = adCmdText
            .Parameters.Append .CreateParameter("?", adVarChar, adParamInput, 50, txtNome.Text)
            .Parameters.Append .CreateParameter("@foto", &HCD, adParamInput, tam, b)
            .Execute
    End With
MsgBox "Salvo !", vbInformation
Set Cmd = Nothing
Con.Close
End Sub

Link to comment
Share on other sites

  • 0
é que não costumo usar "ByVal" e "ByRef" :rolleyes:

A diferença é explicada aqui: http://scriptbrasil.com.br/forum/index.php?showtopic=48769

mas o "Optional ByRef n As Long = 0&" é opicional, então, se colocar algum valor nesse parâmetro ele vai influenciar em algo na função ??? porque dentro da função o "n" vai receber valor (no caso o tamanho final do arquivo).

O parâmetro é opcional. Acontece que eu tinha essa função gravada aqui e ela não retornava o tamanho, n era uma variável declarada dentro dela. Aí, como no caso, eu precisava do tamanho, transformei n num parâmetro por referência para que o tamanho fosse retornado de dentro da função. Só que deixei opcional pra que as chamadas já existentes a essa função (que passavam um só parâmetro - o caminho) continuassem funcionando.

Ou seja, passando ou não o segundo parâmetro a função funciona do mesmo jeito. Se eu não quiser saber o tamanho, não tem necessidade de passar o segundo.

E no caso dessa função como está, o valor da variável original (no caso, tam) passado para n não fazer diferença, porque a função não vai ler o valor do parâmetro n, ela vai é preencher esse valor para depois retorná-lo à variável original. (Na verdade, a função já acessa a variável original diretamente. Como é por ByRef, o parâmetro n vai apontar diretamente para o local da memória onde está a variável tam)

Lembrando que não é necessário fazer desse modo pra encontrar o tamanho, imagino que um UBound() + 1& no array retornado deve trazer exatamente o número de bytes ocupados pela imagem.

só curiosidade...porque não sabia que função retornava mais de um valor...no caso, retornando um vetor de Bytes "b()" e o tamanho do fim do arquivo

A função mesmo, retorna só um. Mas os parâmetros passados por referência podem também ser usados para retornar valores.

Já com o SQL Serve está apresentando o seguinte erro:

Erro2.png

Acho que tinha que ser assim:

Inserir = "INSERT INTO InDat(Nome,Foto)VALUES(?,?)"
...
.Parameters.Append .CreateParameter("Nome", adVarChar, adParamInput, 50, txtNome.Text)
.Parameters.Append .CreateParameter("Foto", adLongVarBinary, adParamInput, tam, b)[/code]

Link to comment
Share on other sites

  • 0

Kuroi...

Com a sugestão o erro passou a ser este:

001-3.png

:mellow:

Como se passa uma variável escalar no VB-6 ? :blink:

Tou achando que o quê tá faltando é isso... <_<

Quanto a explicação do ByVal e ByRef, muito explicativa mesmo ! top.gif

o "Optional" eu já conhecia...sempre vem destacado entre colchetes "[]" nas funções...e o legal é que em algumas funções do VB pode-se ver as "Constantes" e "Types", e depois verificar no Object Browser a variedade de opções de preenchimento.

Edited by Danleonhart
Link to comment
Share on other sites

  • 0

Kuroi, desculpe minha ignorância... mas poderia explicar a necessidade dessa parâmetro :huh:

agora está inserindo normalmente !

Código:

Sub Gravar_Modo_SQL()
Dim Cmd As ADODB.Command
Dim Inserir As String
Dim b() As Byte
Dim tam As Long

b = Por_Em_Byte(camFoto, tam)
Inserir = "INSERT INTO InDat(Nome,Foto)VALUES(?,?)"

Abb
Set Cmd = New ADODB.Command
    With Cmd
            .ActiveConnection = Con
            .Prepared = True
            .NamedParameters = False
            .CommandText = Inserir
            .CommandType = adCmdText
            .Parameters.Append .CreateParameter("Nome", adVarChar, adParamInput, 50, txtNome.Text)
            .Parameters.Append .CreateParameter("Foto", adLongVarBinary, adParamInput, tam, b)
            .Execute
    End With
MsgBox "Salvo !", vbInformation
Set Cmd = Nothing
Con.Close
End Sub

Os tipos dos campos são:

Controle = Integer => (3) = AdInteger

Nome = VarChar => (200) = AdVarChar

Foto = Image => (205) = AdLongVarBinary

Fiz aquela dica que você falou...ver os tipos dos campos do banco, e de retorno recebi os números acima...foi só dá uma olhada na relação deles no Object Browser e configurar os parâmetros adequados :rolleyes: .

VALEU ! Legal.gif

Link to comment
Share on other sites

  • 0

NamedParameters diz se você vai dar nome ou não aos parâmetros. Do modo como você está fazendo, com ?, os parâmetros não têm nome.

Então .NamedParameters tem que ser False. Se você quiser escrever os nomes, como fez usando Access, tem que setar como True, mas deve ter alguma particularidade na sintaxe para o SQL para fazer funcionar, pesquisando talvez dê pra descobrir.

Link to comment
Share on other sites

  • 0
Vou pesquisar sobre isso pois estu achando que tem relação com essa tal variável "Scalar"...sempre que tento passando um nome dá erro apontando para essa variável "Scalar".

Sei lá do que ele tá falando, acho que ele tá se referindo ao nome do parâmetro, ele deve estar achando que @Nome deveria ser uma variável (pois as variáveis que usamos em procedures no SQL tem @ na frente - assim como os parâmetros também, mas enfim...) mas ainda não foi declarada.

Não sei se vai dar pra fazer com parâmetros nomeados com o SQL, mas se der deve ser outra sintaxe. Ou talvez funcione somente com Stored Procedures.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Forum Statistics

    • Total Topics
      152.2k
    • Total Posts
      652k
×
×
  • Create New...