Prepared Statement

  1. 2 months ago

    Nedi F

    May 31 Europe (Italy, Bologna)

    Sto cercando di utilizzare, per la prima volta, la tecnica dei PreparedStatement con Database SQL Server.
    Guardando un po' nella guida in linea e un po' nell'esempio, ho scritto questo codice

    Dim SQL As String
    Dim prepStm As MSSQLServerPreparedStatement
    
        SQL = "INSERT INTO ORDFOR "
        SQL = SQL + "(OF_NumOrd, OF_Agent, OF_Dealer, OF_DatOrd, OF_DatCon, OF_NumFat, OF_DatFat, "
        SQL = SQL + " OF_ImpFat, OF_CosLog, OF_DatSca, OF_DatPag) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
        
        prepStm = DB.Prepare(SQL)
        
        
        prepStm.BindType(0, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)
        prepStm.Bind(0, OF_NumOrd)
        
        prepStm.BindType(1, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
        prepStm.Bind(1, OF_Agent)
        
        prepStm.BindType(2, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
        prepStm.Bind(2, OF_Dealer)
        
        prepStm.BindType(3, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(3, OF_DatOrd)
        
        prepStm.BindType(4, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(4, OF_DatCon)
        
        prepStm.BindType(5, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)
        prepStm.Bind(5, OF_NumFat)
        
        prepStm.BindType(6, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(6, OF_DatFat)
        
        prepStm.BindType(7, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DOUBLE)
        prepStm.Bind(7, OF_ImpFat)
        
        prepStm.BindType(8, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DOUBLE)
        prepStm.Bind(8, OF_CosLog)
            
        prepStm.BindType(9, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(9, OF_DatSca)
        
        prepStm.BindType(10, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(10, OF_DatPag)
        
        
        prepStm.SQLExecute
        

    Su SQLExecute il programma si blocca e non si schioda più: cosa sto sbagliando?

    Grazie.

    Nedi

  2. Hello
    Nedi Freguglia
    the first thing that I observe
    You have to make a small change in your string

    SQL = "INSERT INTO ORDFOR "+_
    "(OF_NumOrd, OF_Agent, OF_Dealer, OF_DatOrd, OF_DatCon, OF_NumFat, OF_DatFat, "+_
     " OF_ImpFat, OF_CosLog, OF_DatSca, OF_DatPag) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "

    tell me if you solved it

    regards

    Raul Juarez Pulache

  3. Nedi F

    Jun 1 Europe (Italy, Bologna)

    Hi Raul, really I don't see any difference between your solution and mine, and in effect the result is the same: it doesn't work.

    Thank you anyway!

  4. Nedi F

    Jun 2 Europe (Italy, Bologna)

    Antonio Rinaldi, aiuto!!

  5. Hello
    Nedi Freguglia

    I do not have SQLSERVER installed on my computer, but I have tried Mysql
    with its code, logically with variations such as making changes MySQL with MSSQL, long with Int
    keeps the record perfectly, I attach the code as reference

      Dim DB As New MySQLCommunityServer
      DB.UserName="root"
      DB.Password="*****"
      DB.DatabaseName="bdsisarpe"
      If DB.Connect then
        
        MsgBox "conexión satisfactoria a Mysql"
        
        Dim OF_NumOrd As integer=4
        Dim OF_Agent As string="AGENT 197"
        Dim OF_Dealer As string="DEALER 197"
        Dim OF_DatOrd As string = "2018-06-03"
        Dim OF_DatCon  As string ="2018-06-03"
        Dim OF_NumFat  As integer = 45
        Dim OF_DatFat  As string ="2018-06-03"
        Dim OF_ImpFat As Double=1145.85
        Dim OF_CosLog As Double=3000.25
        Dim OF_DatSca As string = "2018-06-03"
        Dim OF_DatPag As string = "2018-06-03"
        
        Dim sql As String
        
        sql = "INSERT INTO ordfor(OF_NumOrd,OF_Agent,OF_Dealer,OF_DatOrd ,OF_DatCon,OF_NumFat,OF_DatFat,OF_ImpFat,OF_CosLog,OF_DatSca,OF_DatPag) VALUES(?,?,?,?,?,?,?,?,?,?,?) "
    
        Dim prepStm As PreparedSQLStatement =DB.Prepare(sql)
    
        prepStm.BindType(0, MySQLPreparedStatement.MYSQL_TYPE_LONG)
        prepStm.Bind(0, OF_NumOrd)
        prepStm.BindType(1, MySQLPreparedStatement.MYSQL_TYPE_STRING)
        prepStm.Bind(1, OF_Agent)
        prepStm.BindType(2,MySQLPreparedStatement.MYSQL_TYPE_STRING)
        prepStm.Bind(2, OF_Dealer)
        prepStm.BindType(3,MySQLPreparedStatement.MYSQL_TYPE_DATE)
        prepStm.Bind(3, OF_DatOrd)
        prepStm.BindType(4,MySQLPreparedStatement.MYSQL_TYPE_DATE)
        prepStm.Bind(4, OF_DatCon)
        prepStm.BindType(5, MySQLPreparedStatement.MYSQL_TYPE_LONG)
        prepStm.Bind(5, OF_NumFat)
        prepStm.BindType(6,MySQLPreparedStatement.MYSQL_TYPE_DATE)
        prepStm.Bind(6, OF_DatFat)
        prepStm.BindType(7, MySQLPreparedStatement.MYSQL_TYPE_DOUBLE)
        prepStm.Bind(7, OF_ImpFat)
        prepStm.BindType(8, MySQLPreparedStatement.MYSQL_TYPE_DOUBLE)
        prepStm.Bind(8, OF_CosLog)
        prepStm.BindType(9,MySQLPreparedStatement.MYSQL_TYPE_DATE)
        prepStm.Bind(9, OF_DatSca)
        prepStm.BindType(10,MySQLPreparedStatement.MYSQL_TYPE_DATE)
        prepStm.Bind(10, OF_DatPag)
        prepStm.SQLExecute
        
        If Not DB.Error then
          MsgBox "GRABADO CORRECTAMENTE"
        Else
          MsgBox "ERROR: NO SE PUDO GRABAR "+DB.ErrorMessage
        End If
        
        Self.cmdSalir.SetFocus
      Else
        MsgBox "Error de conexion a MySQL"
      End If

    You have installed the SQL Native Client version 11.00 or higher drivers
    You must first test if there is a connection to the MSSQL SERVER database
    You can try only one or two fields of type string, because they can be the dates or the numbers and so you can solve more quickly
    put in an error message

    I hope to help you in something, comment me

    regards

    Raul Juarez Pulache

  6. Nedi F

    Jun 4 Europe (Italy, Bologna)

    Thank you, Raul, for your support.
    According to your advise, I tried to bind one field at a time: the first three fields are type Integer and String, and everything is OK.
    The problem occurs when I add and bind a date field. I know how to deal with date field when I use the DataRecordset class or when I use a SQL statement, but with prepared statement and binding (due to my lack of experience) I don't know how to solve the problem.

    Nedi

  7. Nedi F

    Jun 4 Europe (Italy, Bologna)

    Sorry...I mean DatabaseRecord class, not DataRecordset class...

  8. Antonio R

    Jun 5 Pre-Release Testers, Xojo Pro Europe (Italy)

    Come è formattato il campo che va in MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE ?

  9. Nedi F

    Jun 5 Europe (Italy, Bologna)

    Ho provato a dargli in pasto la proprietà della classe, che è di tipo Date

  10. Antonio R

    Jun 5 Pre-Release Testers, Xojo Pro Europe (Italy)

    Potresti provare con MySQLPreparedStatement.MYSQL_TYPE_STRING... dovrebbe convertirlo correttamente

  11. Nedi F

    Jun 5 Europe (Italy, Bologna)

    Ok, adesso ci provo.
    Grazie!!

  12. Nedi F

    Jun 5 Europe (Italy, Bologna)

    Niente: non inserisce nulla, e non mi dà nessuna segnalazione di nessun tipo...

  13. Antonio R

    Jun 11 Pre-Release Testers, Xojo Pro Europe (Italy)

    prova con:
    data.sqldatetime
    data.sqldatetime.replace(" ", "T")

    in realtà l'ideale sarebbe utilizzare datetime2 come tipo in mssql visto che questo è più compatibile (al solito MS fa i suoi standard)

  14. Nedi F

    Jun 12 Europe (Italy, Bologna)

    Niente da fare….tutto sommato conviene utilizzare delle stored procedure al posto dei Prepared Statements.
    Tu che dici, Antonio?

  15. Antonio R

    Jun 12 Pre-Release Testers, Xojo Pro Europe (Italy)

    Se è pur vero che sono strane (ad esempio non funziona la modalità a chiamata unica ma solo con il bind del value) a mio avviso se possibile vanno sempre usate.

    Avevo fatto dei test ed ero riuscito a farle andare.
    Magari devo fare un test più mirato per il tuo caso:
    se mi scrivi le coppie campo<->tipo e un esempio di dati che stai tentando di scrivere ti trovo la soluzione.

  16. Nedi F

    Jun 13 Europe (Italy, Bologna)

    Grazie, Antonio!

    Ecco il codice che dovrebbe eseguire degli INSERT in una tabella

        Dim prepStm As MSSQLServerPreparedStatement
        
        SQL = "INSERT INTO ORDFOR " + _
        "(OF_NumOrd, OF_Agent, OF_Dealer, OF_DatOrd, OF_DatCon, OF_NumFat, OF_DatFat, " + _
        " OF_ImpFat, OF_CosLog, OF_DatSca, OF_DatPag) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
        
        prepStm = DB.Prepare(SQL)
        
        
        prepStm.BindType(0, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)
        prepStm.Bind(0, OF_NumOrd)
        
        prepStm.BindType(1, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
        prepStm.Bind(1, OF_Agent)
        
        prepStm.BindType(2, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
        prepStm.Bind(2, OF_Dealer)
        
        prepStm.BindType(3, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(3, OF_DatOrd)
        
        prepStm.BindType(4, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(4, OF_DatCon)
        
        prepStm.BindType(5, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)
        prepStm.Bind(5, OF_NumFat)
        
        prepStm.BindType(6, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(6, OF_DatFat)
        
        prepStm.BindType(7, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DOUBLE)
        prepStm.Bind(7, OF_ImpFat)
        
        prepStm.BindType(8, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DOUBLE)
        prepStm.Bind(8, OF_CosLog)
        
        prepStm.BindType(9, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(9, OF_DatSca)
        
        prepStm.BindType(10, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DATE)
        prepStm.Bind(10, OF_DatPag)
        prepStm.SQLExecute
        
        

    La tabella in questione ha una serie di campi che sono individuabili nella variabile SQL. La natura di tali campi è visibile dai vari BindType. Il codice è eseguito da una classe che ha tante proprietà quanti sono i campi della tabella (e della stessa natura):tali proprietà sono utilizzate nei vari Bind.

    Tieni presente che alcune date (soprattutto la data pagamento OF_DatPag) potrebbero non essere valorizzate (non so come fare in questi casi).
    Nei test che ho fatto comunque le date erano tutte valorizzate.

    Spero di averti fornito sufficienti "indizi": se necessiti di altre informazioni non devi far altro che dirmelo.

    Grazie ancora!

  17. Nedi F

    Jun 13 Europe (Italy, Bologna)

    Il codice che ho postato ha un ? in più nello statement SQL: c'è finito per errore. Anche con il numero corretto di parametri il risultato non cambia.

  18. Antonio R

    Jun 13 Pre-Release Testers, Xojo Pro Europe (Italy)

    Ok.
    Ti chiedevo i tipi originali (nel db) e il tipo di variabile che inserisci perché il problema potrebbe essere quello.

    E dovendo creare una tabella di test per replicare devo sapere la definizione.
    Diciamo che da quello che hai postato:
    OF_NumOrd, OF_NumFat ->INTEGER
    OF_Agent, OF_Dealer -> VARCHAR(200)
    OF_DatOrd, OF_DatCon, OF_DatFat, OF_DatSca, OF_DatPag -> DATETIME (null o NOT NULL)
    OF_ImpFat, OF_CosLog ->DOUBLE

    Da cui potrei creare una tabella con:
    CREATE TABLE ORDFOR (OF_NumOrd INTEGER, OF_Agent VARCHAR(200), OF_Dealer VARCHAR(200), OF_DatOrd DATETIME, OF_DatCon DATETIME, OF_NumFat INTEGER, OF_DatFat DATETIME, OF_ImpFat DOUBLE, OF_CosLog DOUBLE, OF_DatSca DATETIME, OF_DatPag DATETIME)

    Corretto?

    Le variabili per l'esempio:
    Dim OF_NumOrd as Integer=1
    Dim OF_Agent as string="Agente"
    Dim OF_Dealer as string="Venditore"
    Dim OF_DatOrd as new Date
    Dim OF_DatCon as new Date
    Dim OF_NumFat as integer=1
    Dim OF_DatFat as new Date
    Dim OF_ImpFat as double=1000.0
    Dim OF_CosLog as double=200.25
    Dim OF_DatSca as new Date
    Dim OF_DatPag as new Date

    OK?
    Se mi indichi quali campi sono NULLABILI posso verificare anche quel caso (ad esempio penso la OF_DatPag)

  19. Nedi F

    Jun 13 Europe (Italy, Bologna)
    Edited 2 months ago

    I due campi String sono VarChar(50). Tutti gli altri vanno bene. Nel DB l'unico campo che non può essere Null è OF_NumOrd, in quanto primary key.
    Nella realtà vengono tutti valorizzati sempre, tranne OF_DatPag.

    Nelle istruzioni di Bind utilizzo delle proprietà della classe che hanno stesso nome e tipologia dei campi del DB.
    Nel DB i campi data sono di tipo Date (non DateTime)

  20. 7 weeks ago

    Antonio R

    Jun 26 Pre-Release Testers, Xojo Pro Europe (Italy)

    Questo funziona (almeno da me):

    //Non ho inserito il NumOrd perché definito come identity, ma non è quello il problema
    dim p as PreparedSQLStatement=mDB.Prepare("insert into ORDFOR (OF_Agent, OF_Dealer, OF_DatOrd, OF_DatCon, OF_NumFat, OF_DatFat, OF_ImpFat, OF_CosLog, OF_DatSca, OF_DatPag) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
    
    //Uso la sintassi con 3 parametri per far prima, di solito in realtà uso prima il bindtype e poi la execute o select con i parametri
    //ma non funziona nel caso di MSSQL
    p.Bind(0, OF_Agent, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
    p.Bind(1, OF_Dealer, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
    p.Bind(2, OF_DatOrd, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
    p.Bind(3, OF_DatCon, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
    p.Bind(4, OF_NumFat, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)
    p.Bind(5, OF_DatFat, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
    p.Bind(6, OF_ImpFat, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DOUBLE)
    p.Bind(7, OF_CosLog, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_DOUBLE)
    p.Bind(8, OF_DatSca, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
    p.Bind(9, OF_DatPag, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)
    p.SQLExecute

or Sign Up to reply!