He estado trabajando en una base de datos de Access durante las últimas dos semanas y es mi primer proyecto con la herramienta. Lidiar con consultas de adición parece haberse convertido en una pesadilla y es increíblemente frustrante. Más aún porque parece que simplemente ha dejado de funcionar de manera consistente de la noche a la mañana.

La consulta SQL que he escrito es la siguiente:

PARAMETERS noteDetails LongText, noteTime DateTime, srcUserID Long;
INSERT INTO tblNotes (NOTE_DETAILS, NOTE_TIME_CREATED, NOTE_SOURCE_USER)
VALUES (noteDetails, noteTime, srcUserID)

En tblNotes :

NOTE_ID is an AutoNumber
NOTE_DETAILS is a Long Text
NOTE_TIME_CREATED is a Date/Time
NOTE_SOURCE_USER is a Number

La forma en que estoy ejecutando esta consulta es a través de VBA:

Set qdf = CurrentDb.QueryDefs("qerApndNote")
qdf.Parameters(0).Value = txtDetails.Value
qdf.Parameters(1).Value = Now()
qdf.Parameters(2).Value = getCurrentUserID()
qdf.Execute dbFailOnError
qdf.Close
Set qdf = Nothing

' Where CurrUserID is a global long
' txtDetails.Value is a textbox's contents
' Now() is the VBA built-in function to return a date/time combo

Intenté ejecutar esta consulta manualmente desde la barra de navegación, y funciona bien cuando se hace de esa manera.

Sin embargo, ejecutarlo desde VBA ha dado como resultado cosas como que no se haya insertado la fecha / hora, a veces no se inserta una ID de usuario, a veces ambas, a veces incluso falta el texto de detalles.

¿Qué es lo que me estoy perdiendo? ¿Hay algún consejo general que los usuarios de MS Access puedan seguir que yo no? Soy consciente de que NOTA es una palabra restringida en Access, pero realmente no creo que deba aplicarse aquí, ¿verdad?

¡Gracias de antemano!

EDITAR : el formulario desde el que estoy pasando datos se llama frmNewNote y tiene un control llamado txtDetails. Es solo un cuadro de texto normal. Realmente no sé qué más compartir sobre eso.

La función getCurrentUserID está en un módulo, modGlobal :

Public CurrUserID As Long

Public Function getCurrentUserID() As Long
    getCurrentUserID = CurrUserID
End Function

Public Function setCurrentUserID(CurrID As Long)
    CurrUserID = CurrID
End Function

Es lo más básico que puedes conseguir, de verdad. Y nunca hay una circunstancia de que acceda al formulario antes de que se haya llamado a SetCurrentUserID durante su ... ¿sesión? Hay un formulario de inicio de sesión involucrado.

@ Código de Andre para iniciar sesión:

 0            noteDetailsText             This is a note test
 1            noteTimeCreated             9/6/2017 10:28:45 AM 
 2            srcUserID      1

En cuanto a mi arquitectura, es solo el archivo de base de datos en este momento, en el escritorio. Toda la función / sub se ejecuta cuando hace clic en un botón, btnEnter . Hace algunas otras cosas antes de llegar al bit de la declaración SQL: verifica los valores nulos y solicita al usuario las entradas si ese es el caso.

2
user8533487 6 sep. 2017 a las 19:58

2 respuestas

La mejor respuesta

Acabo de recordar algo:

MS Access 2013 llama a consultas de inserción desde VBA con errores extraños

Tiene un parámetro LongText. Estos realmente no funcionan. Consulte también https://stackoverflow.com/a/37052403/3820271

Si las notas ingresadas siempre serán <= 255 caracteres, cambie el parámetro a ShortText.

Si el texto puede ser más largo, tendrá que usar el enfoque de SunKnight0 con una instrucción INSERT concatenada.

O use un Recordset y su .AddNew, que será una cantidad similar de código a su solución actual, pero también estará completamente a salvo de problemas de inyección o de formato.

1
Andre 6 sep. 2017 a las 19:43

Estás haciendo mucho más trabajo del necesario. Todo lo que necesitas es:

DoCmd.RunSQL("INSERT INTO tblNotes (NOTE_DETAILS, NOTE_TIME_CREATED, NOTE_SOURCE_USER) VALUES ('" & Me.txtDetails & "',Now()," & CurrUserID  & ")")

Tenga en cuenta el cambio de txtDetails.Value a Me.txtDetails, que es lo que puede haberlo estado arruinando. Por supuesto, esto supone que el código se ejecuta en el contexto del formulario, de lo contrario, debe obtener el valor del campo de texto utilizando una referencia al formulario.

La única otra cosa a considerar es asegurarse de que Me.txtDetails no tenga comillas simples, así que probablemente use Replace(Me.txtDetails,"'","''") en su lugar.

De esa manera, también puede reemplazar DoCmd.RunSQL con MsgBox para solucionar el problema de la consulta exacta.

0
SunKnight0 6 sep. 2017 a las 17:48