Ah, that's an easy resolving of the underlying problem.
Then in fact private variables help you, because their scope is level of definition and every further call level on the stack. So parameters instead of lprameters would help. A more general solution would need multiple variables, and so overall it wold help if you use private variables for parameters and then the real execution of SQLExec can be in the next or even further down the callstack.
But then nobody can see through this, as you just didn't tell what's really happening.
I wouldn't revert from putting SQLExec into a class, there's a good reason for working that way as you can do general (for any query) but still specific (for sqlexec) error handling within a method wrapping SQLExec, whereas you need to use a few lines for that in every instance of using SQLExec.
I already mentioned Cursoradapters have a slight magic about them in a query you store into a cursoradapter SelectCmd will be able to address it, even though the execution is buried in the native behaviour of the CursorFill method. So once you have a fully prepared cursoradapter object you can do this:
Code:
Local loCA
loCA = CreateObject("yourbasecursoradapter")
Local lcCriteria
lcCriteria = "START"
loCA.Alias = "crsStartvariables"
loCA.SelectCmd = "Select * from Variables where Criteria = ?lcCriteria"
loCA.CursorFill()
So instead of a wrapper of the SQLExec function you could do a general data access class with a CA that does a) make a connection (or uses a public handle), b) may have a prebuilt SelectCmd and result cursor name and even result cursor schema and then c) is used just by creating parameter variables and calling CursorFill(). So a CA class for every query you want under full control about the result cursor schema. A general CA for any query result without that prepopulated schema also is possible, because you can change the SelectCmd and Alias properties on the fly, which already are the main parameters of any SQLExec, you can also make them init parameters, and then you have a two line SQLExec with line 1 creating the CA object and line 2 calling CursorFill on the level of parameter variable definitions. The error handling then can be in the error method of the ca base class and with the help of inheritancce you can have a nice family of data access business objects each with specific error handling and other rules checking, too.
Alone being able to specify the result cursor schema can help when SQLExec infers types not working, eg in MSSQL varbinary(max) may not come over to VFP as blob fields, especially using Native Client drivers instead of the legacy SQL Server ODBC driver series. (Also a reason I asked for your ODBC driver, there can be very differing behavior about them).
Bye, Olaf.