Access - Control error sentencias SQL

 
Vista:

Control error sentencias SQL

Publicado por Francisco Fírvida (6 intervenciones) el 10/10/2013 18:27:38
Hola a todos,
Queria saber si alguien sabe como controlar los errores que se pueden producir al ejecutar una sentencia SQL.
Ej.
dNumeroPpto = 1
sCliente = "Prueba"

sSql = "INSERT INTO PRESUPUESTOS_VENTAS ( "
sSql = sSql & " NUM_PRESUPUESTO,CLIENTE) "
sSql = sSql & " VALUES("
sSql = sSql & NumSQL(dNumeroPpto) & ","
sSql = sSql & CadSQL(sCliente) ")"

CurrentDb.Execute sSql

Al ejecutar esta sentencia, me añadiría el registro a la tabla PRESUPUESTOS_VENTAS, lo que necesito es que si esa sentencia produjera algun error, como p.e. que ese numero de presupuesto ya existiera en la tabla (lo que provocaria error de "Registro duplicado"), que me devolviera un error.
Le estoy metiendo un On Error goto ErrorSQL pero no me sale por esa excepcion.

Alguna idea?

Muchas gracias ante todo
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Neckkito
Val: 529
Plata
Ha mantenido su posición en Access (en relación al último mes)
Gráfica de Access

Control error sentencias SQL

Publicado por Neckkito (1157 intervenciones) el 10/10/2013 20:46:44
Hola!

Hay errores que se producen porque el código es erróneo (entendido esto en sentido amplio), y eso provoca que salte un error llamémosle "tipificado", que se reconoce porque te indica el número de error y su descripción.

Estos errores son los que pueden capturarse y gestionarse a través de un control de errores.

Hay otros errores que se generan no por el código (porque el código no tiene ningún error), sino por el propio Access. Estos errores no te indican ningún número de error. Estos errores no son interceptables por el código porque, como te decía, el código es totalmente correcto.

En tu caso, el código con la SQL es perfecto: se ejecuta y listos. El problema viene en el proceso posterior, cuando la aplicación (Access) se encuentra con que las propiedades del campo no permiten valores duplicados, como es tu caso.

Yo todavía no he encontrado la manera de "manipular" estos errores de aplicación.

En estos casos lo que suelo hacer, dado que conozco la naturaleza del error, es crear un código de control dentro del código que te haga un chequeo previo de las condiciones: si se cumplen ejecutas la SQL; si no se cumplen no la ejecutas.

Es decir, por ejemplo en tu caso lo que podríamos hacer sería lo siguiente:

....
Sub...
Dim elPpto as variant
dNumeroPpto = 1
sCliente = "Prueba"
'Defino la SQL como tu la tienes definida (no la copio aquí)
'Compruebo si ya existe el presupuesto. Si no existe elPpto devuelve un NULL
elPpto=dlookup("NUM_PRESUPUESTO","PRESUPUESTOS VENTAS", "NUM_PRESUPUESTO=" & dNumeroPpto)
If isnull(elPpto) then
CurrentDb.Execute sSql
Else
msgbox "El prespuesto ya existe",vbExclamation,"AVISO"
End if
End Sub
....

Y listos.

Salvo que alguien conozca otra manera de hacerlo (y agradecería que nos lo comente ) esto es lo que yo haría.

Saludos,


http://neckkito.siliconproject.com.ar
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Control error sentencias SQL

Publicado por deneg_nhj (348 intervenciones) el 11/10/2013 01:30:46
Estimado

Te comento la mecanica que utilizo.

1.- La BD de DAO tiene una propiedad RecordsAffected, esta propiedad refleja los registros modificados en la ultima sentencia de Execute. Si utilizas Currentdb para ejecurar el SQL y otra para evaluar la variable RecordsAffected siempre te va a dar cero y eso sucede porque se crea una copia de la BD cada vez que se invoca Currentdb.

2.- Para sortear el problema del punto 1 debes de utilizar una variable estática "La función de abajo lo hace".

Algo como esto

dbLocal.execute "Update tbDummy X = 0"


if dbLocal.RecordsAffected = 0 then
Aquí haces algo con el error, por ejemplo volver a ejecutarlo o cancelar todo el proceso.
endif

*** NOTA *** Si no existen registros que cumplan la condición te regresará 0 , por lo que solo deberás de utilizarla donde sepas que hay registros que resultarán afectados.



3.- Por ultimo para automatizar el proceso, puedes hacer una función para ejecute una sentencia SQL "con el execute" y que evalué el resultado y si trae registros entonces será verdadero y podrás continuar, en caso contrario lo vuelves a intentar.


Bien, espero que le entiendas "Porque yo no le entendí, jajajaja".


Saludos!

deneg_nhj
Visita mi blog www.sgh.com.mx/blog






Está función la puedes encontrar en la web no recuerdo de quien es pero yo la baje si no mal recuerdo de la pagina de Allen Browne.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Public Function dbLocal(Optional bolCleanup As Boolean = False) As DAO.Database
 
  On Error GoTo errHandler
    Static dbCurrent As DAO.Database
    Dim strTest As String
 
  If bolCleanup Then GoTo closeDB
 
retryDB:
    If dbCurrent Is Nothing Then 'Hay una abierta?
       Set dbCurrent = CurrentDb ' Abrimos la BD
    End If
 
    strTest = dbCurrent.Name ' Verificamos el nombre, para ver si está abierta
 
exitRoutine:
    Set dbLocal = dbCurrent
    Exit Function
 
closeDB:
    If Not (dbCurrent Is Nothing) Then
       'Cerramos!!!, si pide limpiar la BD <-- La variable
       Set dbCurrent = Nothing
    End If
    GoTo exitRoutine
 
errHandler:
    Select Case Err.Number
      Case 3420 ' Object invalid or no longer set.
        Set dbCurrent = Nothing
        If Not bolCleanup Then
           Resume retryDB
        Else
           Resume closeDB
        End If
      Case Else
        MsgBox Err.Number & " -- " & Err.Description, vbExclamation, "Error en dbLocal()"
        Resume exitRoutine
    End Select
  End Function
'==========================================================================
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Control error sentencias SQL

Publicado por Francisco Fírvida (6 intervenciones) el 11/10/2013 11:06:33
Muchas gracias a los dos.
He probado y encontré algo parecido a la respuesta de deneg, pero mas sencillo .

Os indico lo que hago:
Defino una variable mas
dim lNum as long

(codigo sql )

CurrentDb.Execute sSql, lnum

if lnum < 0 then
msgbox "error"
else
seguir
end if

Neckkito, espero que tambien te pueda servir.

saludos,
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Control error sentencias SQL

Publicado por Francisco Fírvida (6 intervenciones) el 11/10/2013 11:22:47
Lo siento, pero algo me falla, voy a seguir probando
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Neckkito
Val: 529
Plata
Ha mantenido su posición en Access (en relación al último mes)
Gráfica de Access

Control error sentencias SQL

Publicado por Neckkito (1157 intervenciones) el 11/10/2013 20:27:32
Hola, Francisco:

He estado "toqueteando" un poco el tema en base a lo que comentabas como solución y, gracias a eso, he comprobado que puedes adelantarte al error de Access "forzando" la devolución de un error con su número y descripción a través del Execute.

Te pongo aquí como podría quedar el código con el error número 3022 (cuando el dato que intentamos insertar ya existe y no se admiten valores duplicados).

...
Sub...
on error goto sol_err
dNumeroPpto = 1
sCliente = "Prueba"

sSql = "INSERT INTO PRESUPUESTOS_VENTAS ( "
sSql = sSql & " NUM_PRESUPUESTO,CLIENTE) "
sSql = sSql & " VALUES("
sSql = sSql & NumSQL(dNumeroPpto) & ","
sSql = sSql & CadSQL(sCliente) ")"

CurrentDb.Execute sSql, dbFailOnError
Exit sub
sol_err:
If Err.Number = 3022 Then
MsgBox "La inserción crearía valores duplicados. No se ejecutará la consulta"
Else
MsgBox "Se ha producido el error: " & Err.Number & " - " & Err.Description
End If
End Sub
...

Con el Else del control de errores podrías comprobar si se devuelven otros errores. Si "pillas" sus números de error podrías ir gestionándolos a través del propio control de errores. En ese caso lo que creo que iría mejor sería utilizar la estructura
...
Select case err.number
Case 3022
'Acciones
Case xxxx 'Otro número de error que quieras gestionar
'Acciones
Case yyyy
'Acciones
Case Else
MsgBox "Se ha producido el error: " & Err.Number & " - " & Err.Description
End select
...

A ver si así te sirve.

Saludos,

Neckkito
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Control error sentencias SQL

Publicado por Francisco Fírvida (6 intervenciones) el 15/10/2013 18:16:04
Gracias!!
Trasteando tambien encontré el dbFailOnError, ahora solo tengo que intentar identificar los errores importantes.

Muchas gracias!!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar