And _excellent_ reply. I'm grabbing this email to put as a "gist" on my github account. From my own experience, programmers who come from a "non-relational" background, the world view of how to _properly_ do SQL is difficult.
On Thu, Sep 18, 2014 at 12:14 AM, Keith Medcalf <kmedc...@dessus.com> wrote: > > You cannot do any of these things in any relational database. You can only > do this in navigational databases. There are various kludges which permit > you to simulate navigational abilities on top of relational databases, but > they are all kludges which are performed by various forms of fakery to impose > navigability on top of a model which inherently is not navigable. > > For example, many database drivers can kludge you up what is called a > "keyset" driven cursor. It does this by executing the query and storing a > temporary table containing the primary keys of each table in the query for > each result row (this is stored either in the driver (for a client-driven > keyset) or on the server (for a server driven keyset). When you ask for a > row from the keyset, the primary keys are used to issue a bunch of queries to > "reconstruct" the "present view" of the result that would be at that > navigational location for you. There are also, usually in these same > drivers, what are called "scrollable" cursors. These differ from a "keyset" > cursor in that the query result set is stored in a temporary table (rather > than a keyset table). The driver can then "pretend" there is ordering and > record numbers on the results and can internally reissue queries against the > temporary table and its row numbers so that it appears you can scroll > forwards and backwards and access ra nd > om rows of the result set (this type of cursor is almost always implemented > on the server as a temp table and the only information sent to the client are > the extents of the rowset). The key difference is that keyset cursors can be > used to update the database (since you have the primary keys for the original > data rows stored away) whereas plain scrollable cursors are read only. > > In some systems these types of capabilities exist solely in the drivers. In > others, there is inherent support in the database engine itself. There are > even cases where there is a combination of both, or where you can select > whether the support should be implemented server-side or client-side. In > some cases the choice of implementation method is taken away from you in > order to protect you from doing something "abysmal", such as retrieving the > primary keys for a billion row keyset into driver storage.) > > This is a kludge to give the appearance of navigational capabilities where > they inherently do not exist. > > The other way to do it is the way primitive folks do it -- retrieve the > entire result set into a big list of records in your programs storage, and > then navigate through your list in memory. This is popular with Microsoft > tools, for example, and is why most Microsoft tools take aeons to open (try > to open the event viewer on a busy Microsoft server, or open DSA against a > domain with a several hundred thousand objects. You come in to work and sign > on, then open the tool and lock the screen, then go for breakfast, and > meetings, and lunch. When you return after lunch the tool is ready to use. > Or it has crashed because it ran out of memory.) > > It is also quite common for "bitty system" developers to do this. Everything > works swimmingly well on their test database with 5 customers and 3 products. > However, once the "production" database is loaded that contains a few > thousand customers and several millions of products and components, the > system craps out or is abysmally slow. You then read stories in the > newspaper about how some company (or government) spent hundreds of millions > or billions of dollars on a failed computer system. > > There are still other products which do not provide drivers which kludge up > any of these illusions for you, and the database engine does not have the > baked in complication to assist with the creation of these illusions. For > these systems you have to do all the skull-duggery yourself. SQLite falls > into this category. I don't think anyone was written a "driver" which > implements this in automated fashion either, so you have to "roll your own" > as it were. > >>I'm racking my brain trying to figure out how to get directly to the last >>item in a (potentially) sorted or ordered table. At least oe of the >>tables will be ordered by a name and a date, so uising the rtowid won't work. > > Read all the results until you run out of results. At this point the last > result you successfully retrieved was the last. If this takes too long then, > >>Also, how to traverse a table or cursor in a reverse direction. > > Issue the same query again, and "reverse" the sort order of each column in > the group by clause. You will now retrieve the result set in the opposite > order and the "first" row will be the "last" and the "last" shall be "first". > If you wish to start "in the middle" devise some constraints to add (to the > where clause) which determine the appropriate slicing of the result set. > >>Going from first to last is easy in pysqlite, just use fetchone(). >>Geting directly to the first record is also easy, just open the >>desired table and the first fetch is the first record. > > No, the first fetch returns the first row of the result set. If and only if > you issued a query with an order by clause giving a specific fully determined > ordering to the results is ordering guaranteed. It is the order by clause > which determines the order. If you do not have an order by clause in the > query, then the row that you are calling the "first" row is only that by > happenstance and the gyrational flux of subatomic particles at the time of > the observation. Be aware, however, that like Schroedingers Cat, your > observation of the subatomic gyrations will fix the duality in a random > fashion that may be different for each observation. > >>But, if I'm, for example, at the 10th record of an ordered table >>(cursor), how do I go backward one or more times? > > Issue an appropriate query to generate a result set containing the set of > result rows that you want in the order that you desire, and retrieve them. > >>And how do I go directly to the last? > > Re-issue the query with the order by clause inverted (change ASC to DESC and > DESC to ASC for every item in the order by clause). Now when you retrieve > the "first" row you will get what was the "last" when ordered in the opposite > direction, and the "last" will now be "first". > > Set theory, relational algebra, and the higher mathematics on which > relational databases are built is both extremely complex and amazingly simple > all at the same time. The first thing you have to do is realize that there > is no such thing as "order". If you want "order", you must ask for it > explicitly. Relying on happenstance is not a substitute and is unwise. > Also, the row-by-row access wherein you think you are "stepping through" a > result set is an illusion which is created by the technological limitations > resulting from adapting relational and set operations to the unfortunately > linear basis of human procedural implementation of the technology. > > See: http://www.sqlite.org/cvstrac/wiki?p=ScrollingCursor for simple > examples. There are certainly lots of others. > > > > > _______________________________________________ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users -- There is nothing more pleasant than traveling and meeting new people! Genghis Khan Maranatha! <>< John McKown _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users