Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

My app suddenly tells me a cursor cannot be accessed... 6

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
585
PH
I have been building my app for quite some time now, and i though its working perfectly until i stumbled to a one error... "cannot access the selected table. (cursor)" then suddenly my combobox using the cursor disappears... i don't know where i may have committed an error... I did not post my code, i just want to understand how a cursor works, how is it being closed, or when it is open, how long? does it really close if i have chosen another table(not a cursor) or another cursor? and other things about vfp cursor.... Please help me understand.... Thanks...
 
The last i have done is, i have created a new cursor... does it close the first opened cursor? if so? Please teach me how to go back to the first opened cursor so to avoid the error "cannot access...." Thanks
 
I found the culprit... when i remove this part in my update button it work ok... but what am i missing here? please help thanks....

SELECT ALLTRIM(sname) + ", " + ALLTRIM(fname), idnum FROM tsulat ORDER BY sname, fname INTO CURSOR csrdemo READWRITE
 
Maybe you already have another cursor named csrDemo. This seems to be a name just given to you as demoing a query. You have to choose unique names for all your cursors, or they overwrite existing ones. You don't get an error or warning about using a name twice for a cursor, the second query INTO CURSOR with same name overwrites the other. And while that doesn't error or warn you, it can cause all kind of problems with controls already bound to the previous cursor. Better name your cursors with a proper name telling what data is to be found in it. In this case it would be a list of names, wouldn't it? So name that one crsFullNames. And also look into all other code generating another crsDemo cursor and look for a better name for that.

Chriss
 
Mandy,

Chris has given you the specific information you need. But let me try to answer your more general question about cursors and how they work.

As you probably know, a cursor is simply a temporary table. It has most of the characteristics of an ordinary table (that is, a DBF). The most important difference is that when it is closed, it gets deleted.

You can create a cursor explicitly, using CREATE CURSOR, or you can create it to hold the results of a SELECT - SQL statement, which is what you are doing. In the latter case, the cursor is read-only by default. If you want to update the cursor in any way, add READWRITE to the SELECT (again, as you are doing). (You also need READWRITE if you want to index the cursor.)

Unlike DBFs, cursors don't have a path. (They physically exist in your Windows Temp folder, but you don't need to know that.) This implies that every open cursor in your application has to have a unique name. If you create a cursor with the same name as one that is already open, that latter one will close and therefore be deleted.

One other point regarding your SELECT statement (not directly related to the issue of cursors):

Your first expression is [tt]ALLTRIM(sname) + ", " + ALLTRIM(fname)[/tt]. The problem with that is that it is variable length - different people will have different length names. To determine the width of the first field in the cursor, VFP looks at the first record in the source table. So if, in that record, the name is 8 characters wide, then the cursor field will be 8 characters wide. If the names in subsequent records are longer than that, they will be truncated. That is not what you want.

The solution is to make the expression fixed length, perhaps like this:

[tt]SELECT PADR(ALLTRIM(sname) + ", " + ALLTRIM(fname), 25), ....[/tt]

That will make the field 25 characters wide in every record.

Also, when you have an expression like this in a SELECT, the corresponding field in the result cursor will have an arbitrary name - something like Expr_1. This does not harm, but it would be better to give it a name that is more meaningful. You can do that by adding an AS clause:
[tt]
SELECT PADR(ALLTRIM(sname) + ", " + ALLTRIM(fname), 25) AS FullName, ...[/tt].

I hope the above will help you to better understand what is going on when you use cursors.

Mike






__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mandy,

Mike added something, but mainly stressed out once more that names have to be unique.

Well, to add to this, the topic here is scope, in the bigger picture. Name collisions are rarely good in general. But you do use things with same name, when you can scope them with a smaller scope. If you have a loop you can use i as it's loop variable For i = 1 to 10. And ideally you do declare i as LOCAL i. If you don't and within the loop call a function that again uses i you can get into trouble. If all separate methods declare their variables local, they can all use the same name, as that name still only means the local variable and not any of the other code.

In cursor names, the boundary of the scope is the datasession. I guess you've seen and used the datasession window where all open tables and cursors are listed by their alias name. It's there you can't repeat a name. And that scope is not bound by the current method or event, it may not even be bound by the current form, it can be the general datasession shared by the whole application. So one step for more privacy here is to at least have private datasessions per form.

Still, if you do a query into a cursor for one combobox in one click of one button and then another query into a cursor for another listbox of the form, or grid, or whatever. The can't have the same name just like the for variables can have the same name and not mix with one another. The names of the cursor are the workarea names of the datasession and can only repeat in different datasessions.

Scoping is really an important thing to know about, many errors go back to missing to put something int the smallest possible scope so it doesn't clash with anything else. You can even get a problem if a form uses unique names for all its query results, if it doesn't have a private datasession and you run two instances of the same form. Say a form displays all fields of a record to edit it i all details, then you could use two instances to show two different records to compare them. But that'll only work when they each have their own private datasession.

If you combine code from several answers without looking for such name clashes you of course get into trouble. So don't take any code too literally. It always has to be adapted and names are just one part of that adaption to your use case.

This problem, especially since we're seeing it's about a person list, can easily occur when you do want to use the same data, the same person list for selection of two persons, for examole. You can't reuse the saame combobox as using one the other will also change it's currently selected person, you'd really need two cursors for say Quarterback and Wide Receiver just because they both are persons from the same team and thus same name list.

Chriss
 
Wow!!!!! just wow Mike and Chriss.... you always give an outright, comprehensive and detailed answer..!!!!! To Mike Thanks for the examples... im learning a lot... and to Chriss your elaboration made it clear to me, and made decide to really change some of my codes for the better.... Thank you so much for being so generous.... God bless....
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top