Places – Conversion of Place Details to Places #places #placedetails #update

So you have your Place List all nicely structured having worked through and split Places into Places and Place Details and it all seems ticketyboo. Now you need to export your database to some other website or software which does not support the way RootsMagic exports Place Details and POOF! – you’ve been caught in another proprietary feature trap. Wouldn’t it be nice if RootsMagic had an option in Export for Place Details and Place to be combined and outputted as standard GEDCOM PLACes recognised by every GEDCOM compliant program? Until that happens, here is a possible workaround that modifies the data in your database.

Places-ConvertPlaceDetailsToPlaces.sql rev 2015-05-15 changed EventTable.SiteId backfill from -1 to 0 and test from <>-1 to >0; correcting either an original error or responding to a change in the RootsMagic value for an event not having a Place Detail.

Combines Place Details and Master Place into Places. This script should run with any SQLite3 manager having a (fake) RMNOCASE collation. One of its effects is to set a flag in the combined Places that the following script can use to reverse the combination.

Places-UnConvertPlaceDetailsConvertedToPlaces.sql
For those combined Places with the flag set by the first script, this one splits the Place into Place Detail and Master Place. The flag disappears if the combined Place has been edited so such Places can only be split manually. Also, if the Master Place has been deleted or its name modified, then the Combined Place is not split by the script, except, possibly for those Master Places that are a substring of the original, in which case, the result will be a bit of a mess. This script is really an UNDO to provide an escape if you inadvertently ran the first script on your master database, not on a copy, and have no backup.

TMG to RootsMagic Migration #tmg

This page provides an overview of the utilities available on this wiki that may help you with your migration of a TMG Project to a RootsMagic database. An example of what TMG Refugee Mike James did is described at https://lists.rootsweb.com/hyperkitty/list/tmg-refugees.rootsweb.com/thread/199856/. It is important to note that there may be considerable cleanup and data manipulation to be done in TMG first in order to have as complete a data transfer as possible because RootsMagic does not replicate all the features of TMG.

These pages have been tagged “TMG” because they apply to artefacts in databases imported from TMG:

Of course, once your TMG data is in a RootsMagic database, you are able to apply any of the 200-some SQLite queries available here and to develop your own.

Marriages, Length of #marriage

This script answers the question, “How long have marriages lasted?”. For each Marriage and corresponding Annulment or Divorce event for a couple,
it extracts the year of the events and also gets the year of the death of the earlier of the two to have died. It then calculates the length in time between the year of the marriage event and the earliest of the years of the Annulment, Divorce and Death events as the length of the marriage. In the absence of a year for any of these terminal events, it uses the current year from system time. Results are limited to 99 years max.

MarriageLength.PNG
Screen clip of results of query on a small test database in SQLiteSpy.

The second last row in the example is the special case of a couple that divorces and remarries each other; the Length of the second marriage is correct but the Divorced year throws a curve visually. It could be suppressed with a some more coding but is a rare state.

The Died year comes from the Person’s DeathYear field in the NameTable, not directly from the Death or Burial facts, so it is advisable to use File > Database Tools > Rebuild Indexes before running the script to ensure that the DeathYear is sync’d to the latest edits or additions of Death/Burial events.

When there are multiple events of a given type, this script probably extracts the year of the first entered; it could be enhanced to select the Primary.

MarriageLength.sql

Ancestors Query #pedigree

Intro

This query lists all the ancestral lines for a given RIN in your database out to the 13th generation. It is just a table of RINs but could be extended to provide names et al. More significantly, it can be the basis of other queries that need to follow ancestral lines. One of these, already developed is Ancestors Named Group which refreshes the membership of a specially named group in a RM4 database.

AncestorsScreenshot-Spy.PNG
From SQLiteSpy showing the full ancestral lines for three persons plus part of a fourth. Use SQLite Developer or Expert Personal to specify the starting person’s RIN when the query is run – absolutely necessary for large databases.

There was earlier discussion about the need for program recursion for ancestral lines in Set Living Flag and in Another version of a Set Living query. This query does not achieve recursion as it seems quite likely that it cannot be accomplished within SQLite; a higher level language making calls to SQLite seems necessary. However, the script appears amenable to programmatic generation so that instead of recursive calls to SQLite, a dynamic script itself could be written to cover the desired number of generations. RootsMagic 4 may do it either way as the number of generations is a required input.

No attempt was made to filter on the type of relationship (blood, adoptive) between child and parent so the results include all kinds of ancestry.

Download

Ancestors.sql

Usage

This query uses a runtime parameter for the entry of the RIN of the person whose ancestral lines are to be generated. If left blank, or if your SQLite manager does not support runtime parameters, it will attempt to generate the ancestral lines for EVERYONE in your database. This will be very sloooow and may crash the program. SQLite Expert Personal and SQLite Developer ($29 version) do work with the runtime parameter; SQLite Spy skips over it.

Discussions & comments from Wikispaces site

ve3meo

Comment: “…the need for program recursion for ancestral lines …”

ve3meo
03 September 2018 19:37:05

ve3meo Mar 28, 2014

SQLite 3.8.4.1 and somewhat earlier introduced the WITH clause with the RECURSIVE option which should allow ancestral queries in a tree. The current version of SQLite Expert Personal supports this new clause but SQLite Spy does not.
ve3meo Mar 28, 2014

My first success with recursion in SQLite: Ancestors+Query+-+Recursive

Children – Set Order by Birth SortDate #child #family #sortdate #update

There have been recurring wishes expressed in the RootsMagic Forums for an enhancement to globally sort each family of children in the order they were born. For example, have a look at this thread, Sorting all children in the database by birth order. Expressed there are good reasons to be cautious about such an operation but, for some users, the possibility of adverse positioning of children without dates is outweighed by the time saved in organizing those who do. Until RootsMagic does offer such a feature, here is a script that sorts children by birth date.

While executing the script is straightforward, the underlying procedures involve several temporary SQlite Views and a temporary Table. It tries to pick out the dominant event for a person from his/her collection of Primary and non-Primary Birth and Christening events. A single Primary Birth with date is handled best; multiple Primaries or multiple events of the same type in the absence of a Primary may give an undesired order if dates overlap with another child.

The script only updates the child-sorting value (ChildTable.ChildOrder) of those children with a birth-type event having a SortDate and only for those families in which all children have said SortDate. The ChildOrder value of other families is left unchanged. Thus, it should be safe to use this script on a database for which some families have children lacking a birth-type fact or a SortDate for same; it will not affect the order of children whether they are still in the sequence they were added to the family or were subsequently manually rearranged.

To find families which still need to be rearranged manually after having run this script, see Children – Needing Manual Arranging.

It is the SortDate of the birth-type event which is the sorting key, not the Date. This means that users can enter a Birth fact without a Date or with a text Date (unrecognised date format) but with a SortDate estimated to be appropriate and what they might have in mind were they manually rearranging the children. The child order would then be reconstructed correctly by the script.

Almost any SQLite3 manager should be capable of executing this script. As usual, make a backup or work on a copy of your database file so you can get back to where you were before the script executes if you don’t like the outcome.

Children-SetOrderByBirthSortDate.sql
2015-01-22 1st release
2015-01-22 rev to preserve the order of children in families where 1 or more have no birth sortdate or no birth fact.
2015-01-24 rev to correct the override of valid Christen SortDates by empty Birth SortDates

Children – Needing Manual Arranging #child #family #sortdate

After running the query Children-SetOrderByBirthSortDate.sql, there may remain families that need to be manually arranged because one or more of the children has no birth-type fact or has a dominant birth-type fact with no date. This query produces a list of the parents who have such children. Look up and select one of the parents in the Sidebar Index with Family as the Main View and edit as needed.

This query also returns families with a single child; it is helpful in TimeLine and other views and reports to have at least an estimated date of Birth, even just a sort date.

Children-NeedingManualArranging-2.sql

2015-01-23 1st release
2015-01-24 rev to show count of children in family
2015-01-24 rev2 to make standalone, using the WITH syntax with Common Table Expressions for brevity

Discussions & comments from Wikispaces site


thejerrybryan

Bug?

thejerrybryan
19 August 2016 14:16:54

There seems to be something wrong with the script. It begins with WITH statement instead of with a SELECT statement. It may be a valid construction, but if so then I’m not familiar with it. And any case, it fails when run with SQLiteSpy.

Jerry


thejerrybryan

thejerrybryan
19 August 2016 14:19:11

Oops, I see that rev2 changed it to use the WITH syntax with which I’m not familiar. So I guess the syntax is valid. But it doesn’t seem to work with SQLiteSpy.

Set Living Flag #update #living

Superseded 2015-01-25. See Living Flag – Set Globally.

Discussion in RootsMagic-Users pointed out some limitations with the Set Living tool in RootsMagic and the risk of unsetting persons that have been previously set correctly. This page discusses how SQLite might help and is intended to start the development of some useful queries.

The Living flag is stored in the PersonTable in the column named ‘Living’. It has two values: 1=True (Alive), 0=False (Dead).

This query can set all persons to the same state:

UPDATE PersonTable
 SET Living=0; -- Dead 0, Living 1

This query can find all persons with a Death fact:

     -- Persons with death facts
     SELECT PersonID FROM PersonTable, EventTable
      WHERE PersonID=OwnerID
      AND EventType=2;

This query can find all persons with an Individual fact (excluding Family facts) before a given year (1906, in this example):

     -- Persons with any Individual facts dated earlier than 1906
     SELECT PersonID FROM PersonTable, EventTable
      WHERE PersonID=OwnerID
      AND OwnerType=0
      AND DATE LIKE 'D%'
      AND substr(DATE,4,4)<'1906';

We can combine these into one query that will set the Living flag to False for persons with a Death fact or having an individual fact dated earlier than 1906:

UPDATE PersonTable
 SET Living=0 -- Dead 0, Living 1
 WHERE PersonID
 IN (
     -- Persons with death facts
     SELECT PersonID FROM PersonTable, EventTable
      WHERE PersonID=OwnerID
      AND EventType=2
     UNION
     -- Persons with any Individual facts dated earlier than 1906
     SELECT PersonID FROM PersonTable, EventTable
      WHERE PersonID=OwnerID
      AND OwnerType=0
      AND DATE LIKE 'D%'
      AND substr(DATE,4,4)<'1906'
     )
;

This query can be extended to include Family facts (Marriage, Divorce, etc.) older than the given year. We’ll leave that to later or for someone else to add.

So that’s all well and good but for a lot of ancestors, there may be no events, let alone dates. If no Death fact has been entered, then the above queries will leave the Living flag alone; if it was set to True, that’s the way it will stay. It would be great, therefore, to set the Living flag to false for all ancestors and children of some person whose events occurred before the trigger year of, say, 1906. This is probably not readily done within SQLite because it requires a recursion routine through PersonTable and FamilyTable. It can readily be done in a high level programming language that calls SQLite and operates on the results with additional calls. You can see the problem of doing what is essentially the Pedigree tree by examining this 5-generation paternal line query:

SELECT P1.PersonID||','||P1.FatherID||ifnull(','||P2.FatherID,'')||ifnull(','||P3.FatherID,'')||ifnull(','||P4.FatherID,'') AS Pedigree
FROM
(SELECT P.PersonID, F.FatherID FROM PersonTable P , FamilyTable F
 INNER JOIN PersonTable H ON(F.FatherID=H.PersonID)
 WHERE P.ParentID=F.FamilyID) AS P1
LEFT JOIN
(SELECT P.PersonID, F.FatherID FROM PersonTable P , FamilyTable F
 INNER JOIN PersonTable H ON(F.FatherID=H.PersonID)
 WHERE P.ParentID=F.FamilyID) AS P2
ON (P1.FatherID=P2.PersonID)
LEFT JOIN
(SELECT P.PersonID, F.FatherID FROM PersonTable P , FamilyTable F
 INNER JOIN PersonTable H ON(F.FatherID=H.PersonID)
 WHERE P.ParentID=F.FamilyID) AS P3
ON (P2.FatherID=P3.PersonID)
LEFT JOIN
(SELECT P.PersonID, F.FatherID FROM PersonTable P , FamilyTable F
 INNER JOIN PersonTable H ON(F.FatherID=H.PersonID)
 WHERE P.ParentID=F.FamilyID) AS P4
ON (P3.FatherID=P4.PersonID)
;

It produces results like this:

Pedigree
1,116
4,7
5,7
6,254,155,829,138
8,829,138,821
11,829,138,821

A starting person’s RIN is on the left, father next to the right, grandfather next, etc. Results could be constrained to those first persons having old event dates and an UPDATE of the Living flag to 0 for each PersonID (RIN) in that person’s list of paternal parents. However, we would need to grow the query with another LEFT JOIN for each additional generation, hence the need for a recursive routine that would re-use the same core query for each generation until the last ancestor was found. And this was just the paternal line – to add the maternal line and each set of grandparents at each generation is unwieldy without recursion.

If someone can find a way to recurse using SQLite, that would be great; otherwise, some high-level programming is required.
[inline comment: “find a way to recurse using SQLite”

external image user_none_lg.jpg ve3meo Apr 13, 2014

It is now possible: Ancestors+Query+-+Recursive

]

Discussions & comments from Wikispaces site


thejerrybryan

Recursive Query

thejerrybryan
04 July 2011 02:23:38

I have been away from the computer most of the day, but prior to that I had already completed a series of queries that are very similar to the ones you you just posted. I was planning to post them when I got back on the computer tonight. I’ll try to get mine posted as soon as I can, just as a way to compare notes.

I don’t know of any way to do the kind of recursion with SQL that would be required to do something to “all ancestors”, but my update to “set parents of those born before 1906 to not living” can be run multiple times, and each time it would pick up at least one new generation. So we can sort of fake out a recursion simply by running the same update a bunch of times.

It will probably be tomorrow before I get anything else posted.

Jerry


ve3meo

ve3meo
14 April 2014 02:34:12

Have a look at Ancestors+Query+-+Recursive

Tom

Inline comments


ve3meo

Comment: It is now possible: http://sqlitetool…

ve3meo
14 April 2014 02:40:35

It is now possible: Ancestors+Query+-+Recursive

Another version of a Set Living query #living

Superseded 2015-01-25. See Living Flag – Set Globally.


I’m posting my version of SQL for Set Living. It proves to be remarkably similar to Tom’s.

SQL #1, we turn on the Living Flag for everybody in the database. Essentially, we make everybody private and then followup later by setting individuals as not private when they don’t need to be.

--                             Start by privatizing everyone in the database
 
UPDATE PersonTable
  SET Living = 1     -- 0 is not living, 1 is living
  WHERE Living != 1  -- In case it's faster not to update the ones that are already set to living
;

This code differs from Tom’s in that it includes the WHERE Living != 1 clause. The idea is to improve performance slightly by only setting to 1 those flags that are not already 1. In most programming contexts, this would be a silly distinction to make. In a procedural language such as C/C++, I would never consider code such as if (x != 1) x = 1 when a simple x = 1 would do, and indeed the simple form would run faster. But disks are vastly slower than main computer memory and it seems to me that avoiding the write operation associated with SET LIVING = 1 whenever possible might improve performance. But this case the UPDATE runs so quickly either way that I can’t prove which is faster. However, in later queries in this sequence it turns out that it’s important to keep the number of rows being operated on as small as possible, not so much for performance reasons as for other reasons.

SQL #2, we turn off the Living Flag for everyone whose birth date is before 1906.

--                             Unprivatize everyone born before 1906
 
UPDATE PersonTable
  SET Living = 0
  WHERE PersonID IN
    (
     SELECT P.PersonID
       FROM PersonTable AS P
              INNER JOIN
            NameTable AS N ON ( (P.PersonID = N.OwnerID) AND (N.NameType = 0) )  -- Use only the primary name table entry
       WHERE N.BirthYear > 0     --  BirthYear Exists
                AND
             N.BirthYear < 1906
    )
;

This is a case where I like Tom’s code much better than mine. Mine uses the birth year from the NameTable, which is not as reliable as using the EventTable as does Tom. Also, mine only uses the birth date, whereas Tom’s code uses any fact date from the EventTable. So his code is going to detect more people who should have the Living Flag turned off than mine. I had intended my code as a quick and dirty proof of concept, and I had intended to go back and reference the EventTable later with my final code. In looking Tom’s code to fully interpret dates, it seemed more complicated than I wanted to deal with until I had completed my proof of concept. But Tom already wrote very simple code to interpret dates as needed by this query.

However, Tom’s code at this point also includes turning off the the Living Flag for every individual who has a Death Fact, irrespective of what date (if any) is associated with the Death Fact. That’s an important item to accomplish, but my overall process requires that it be left until last.

SQL #3, we turn off the Living Flag for the parents of everyone whose Living Flag has already been turned off. It’s essential at this point in the process that the only reason the Living Flag has been turned off for anybody is because they have an Event Date (any event) prior to 1906. The parents of any such individuals are guaranteed to be deceased. But if the Living Flag is turned off for somebody because they have a Death Fact and the Death Date is 2007, then there is no guarantee that the parents are deceased.

--                             Unprivatize parents of everyone who is already unprivatized
 
UPDATE PersonTable
  SET Living = 0
  WHERE PersonID IN
    (
          SELECT PP.PersonID
            FROM PersonTable AS P
                   INNER JOIN
                 FamilyTable AS F ON (F.FamilyID = P.ParentID)
                   INNER JOIN
                 PersonTable AS PP ON (F.FatherID = PP.PersonID)
           WHERE ( (P.Living = 0) AND (PP.Living = 1) )
 
          UNION
 
          SELECT PP.PersonID
            FROM PersonTable AS P
                   INNER JOIN
                 FamilyTable AS F ON (F.FamilyID = P.ParentID)
                   INNER JOIN
                 PersonTable AS PP ON (F.MotherID = PP.PersonID)
           WHERE ( (P.Living = 0) AND (PP.Living = 1) )
    )
;

A UNION is required to get both the father and the mother. But once you figure out how to do the father, you just clone the father code to make it into the mother code and combine the two with UNION.

It took me a long time to figure out how to do this UPDATE. The primary conceptual problem was understanding how to reference both the PersonTable.PersonID of the person and the PersonTable.PersonID of the parents in the same sub-query, and then how to pass the correct PersonID out of the sub-query back to the query on the outside of the sub-query. In retrospect, it seems obvious and simple. But before I figured it out, it seemed almost impossible. I plan to post a separate "lessons learned" page about just that issue.

Note that contrary to intuition, SQL #3 doesn’t need to look at any dates whatsoever because the heavy lifting on dates has already been completed in SQL #2. And if I were to change SQL #2 to look at the dates of all fact types as in Tom’s code, I still would not need to change SQL #3 at all.

As Tom pointed out, the problem at this point is that you really need to run a recursion on this query, and to run the recursion enough labels deep to get all the ancestors, not just the parents. I can’t think of any way to accomplish such a recursion within a single UPDATE. But SQL #3 can be run as many times as you wish, and each time it is run it will get one additional generation of ancestors. But how many times should you run it? To that end, we can do the following.

SQL #4, for which individuals (or for how many) could we turn off the Living Flag if we ran SQL #3 again.

SELECT Z.PersonID           -- or SELECT COUNT(Z.PersonID)
  FROM
    (
          SELECT PP.PersonID
            FROM PersonTable AS P
                   INNER JOIN
                 FamilyTable AS F ON (F.FamilyID = P.ParentID)
                   INNER JOIN
                 PersonTable AS PP ON (F.FatherID = PP.PersonID)
           WHERE ( (P.Living = 0) AND (PP.Living = 1) )
 
          UNION
 
          SELECT PP.PersonID
            FROM PersonTable AS P
                   INNER JOIN
                 FamilyTable AS F ON (F.FamilyID = P.ParentID)
                   INNER JOIN
                 PersonTable AS PP ON (F.MotherID = PP.PersonID)
           WHERE ( (P.Living = 0) AND (PP.Living = 1) )
    ) AS Z
;

So we can run SQL #3 and SQL #4, followed by SQL #3 and SQL #4, over and over again until SQL #4 yields no rows. At that point, SQL #3 will have done all it can do and we can proceed to SQL #5.

For this query, P.Living in the sub-query is the Living Flag for the individual, and PP.Living in the sub-query is the Living Flag for the parent of the individual. The WHERE statement is coded as WHERE ( (P.Living = 0) AND (PP.Living = 1) ), which tests for situations where the individual is not living but the parent is still flagged as living. And remember that the not living condition at this point is strictly due to event dates, not yet on the presence of a death fact. So it would be sufficient to code the WHERE simply as WHERE P.Living = 0 in the SQL #3. But writing the WHERE statement as it was written is more efficient than just testing for P.Living because it keeps the number of rows in the sub-query as small as possible. And more importantly, SQL #4 will not produce the correct results without testing both P.Living and PP.Living.

SQL #5, turn off the Living Flag for all individuals who have a death fact. It is now safe to do so because we have done everything we can do with ancestors.

--                             Unprivatize everyone with a valid death date
--
--   We separate the processing of the death year from the processing of the birth year because
--   we need to process ancestors before we unprivatize based on the existence of a death date
 
UPDATE PersonTable
  SET Living = 0
  WHERE PersonID IN
    (
     SELECT P.PersonID
       FROM PersonTable AS P
              INNER JOIN
            NameTable AS N ON ( (P.PersonID = N.OwnerID) AND (N.NameType = 0) )  -- Use only the primary name table entry
       WHERE
         N.DeathYear > 0         -- Death year exists, doesn't matter what it is if it exists
     )
;

My code tests for the presence of a death date, whereas Tom’s code tests for the presence of a death fact. Tom’s code is complete and mine is not. I need to change mine to match Tom’s.

Jerry

Discussions & comments from Wikispaces site


ve3meo

Comment: “…really need to run a recursion on this query…”

ve3meo
03 September 2018 19:43:31

ve3meo Apr 13, 2014

Maybe there is now a way: Ancestors+Query+-+Recursive

Living Flag – Set Globally #living #update #recursive

Finally! A script that sets the Living flag globally without having to be run repeatedly until all ancestors are accounted for. It does so with the recursive query feature introduced in SQLite3 in 2014 (see the page Recursive Queries – Ancestors and Descendants for more background). This script supersedes prior efforts by Tom and Jerry, respectively:
Set Living Flag
Another version of a Set Living query

It is simple enough to set the Living flag to false when a person has a Death fact. The previous scripts went further than that, e.g., deeming a person to be dead if their Birth was more than 105 years ago, as is the case with RootsMagic. Where they came to a halt or grinding reiteration was the need to deem dead all ancestors of all such persons deemed dead.

This new script expands on the deemed dead criteria and utilises a variant of the recursive query referenced above to cover all their ancestors. Here is an outline of the expanded criteria for setting the Living flag to False (for dead):
1. person with individual or family events before current year less 105, e.g., 1910 in 2015;
2. person whose spouse has individual events before this cusp year;
3. children of persons with birth before a certain year or death before a later year should be deemed dead (if person born >105 yrs ago deemed dead, then
a) child of parent born > (105 + 25) yrs ago could be deemed to have been born around 105 years ago and now dead
b) child of parent who died > 105 years ago can be deemed to have been born around the same time and now dead;
4. spouses of persons deemed dead are probably also dead;
(arguably a bit risky but, without it, many ancient spouses can be left Living)
5. ancestors of all the above persons;
6. person with death fact;

For everyone else, the script sets the Living flag to true.

From initial testing, the results look pretty reliable. I think there could be isolated instances of a person deemed living when they should be dead. For example, any person with more than 3 generations of descendants, none of which have any dated events or a Death fact – a pretty unlikely scenario. That said, it is desirable for many other reasons that an estimated era for Birth and Death should be entered and that would also resolve this issue.

A complementary script sets color coding to Red for Living flag true and to Green for Living flag false.

Both scripts should run on any SQLite3 manager compiled with SQLite 3.8.3 or later.

LivingFlag-GlobalSet.sql
ColorCode-byLivingFlag.sql
2015-01-25 1st release

SQLiteManagers #sqlitemanagers

SQLite Management Tools : a comprehensive table for multiple operating systems but not updated since 2011.
The following table describes a few tried by one member of this wiki. The page SQLite Managers for Mac OS looks into some for the Mac.

WinMacProductReviewRating
TomH
YNSQLite Expert PersonalFree subset of the $59 Professional version. Excellent results display, sort, filter, thumbnails of images. BLOB viewer/editor. Copy/paste for results export. Save/load SQL files. Supports loadable extensions including most compatible fake RMNOCASE. Supports runtime parameters. Best at handling very large databases, large result sets and multiple open databases. Very frequently updated.
2021-07-18: current version is 5.3
8.8
YNSQLiteSpy

alternative SQLite Spy download link

Free, basic, clean manager capable of bypassing the RMNOCASE obstruction by using a fake collation. Fastest display of table data; sort by column with both numerical and ASCII fields. Export results by copy to clipboard and paste to Excel or text editor. Export/Import SQL. Frequently updated. 1.9.0 supports loadable extensions with potential for RM date processing and other lengthy expressions to be made custom functions. Can bog down on very large intermediate or final results sets.
2021-07-18:: version 1.9.15 released 8 Feb 2021
8.5
YNSQLite DeveloperWere it not for its $29 license, this one would tie or be first. Only one to have choice of user named UniCode collations, hence a substitute for RMNOCASE and no more COLLATE NOCASE overrides. Has good sorting (no numerical sort), filtering, bookmarking and exporting of results. Export/import SQL files. SQL structured formatting. NB: the free Lite version lacks the Collation and some other tools. Good support for bug fixes.
2021-07-18: latest release was 4.2 in 2016
8
YYSQLitemanSimple, reliable but no visual query builder. Good error handling. Can export and import SQL files and save SQL Views. Development appears to have stalled in 2010.
2021-07-18 new website; $1/mo subscription model “native UI” apps for Windows 10 and macOS.
6
YNDBTools DBManager StandardMore professional, commercial. Seems complex and powerful but freeware version out-dated (2007) and restricted.
2021-07-18 no further development since 2007
6
YNSQLite2009 ProAttractive GUI. Fast visual query builder. Unreliable – crashed on some queries or views with poor error handling (Jan 2010). Version 3.7.6.3 as of 2011-05-20 still does not save or load a SQL file – must copy to/from clipboard; takes almost twice as long as SQLiteSpy to execute LifeLines-OO.sql on a large database (117MB). Current 3.8.3.1 (2014-02) has not been tested.
2021-07-18 website uninformative; Software Informer shows latest version as 3.8.3.1 released in 2016
5
YYSQLiteStudioVersion 3 (2014-12) under review; promising.
2021-07-18: current version is 3.3.3
7?
YNSQLite AdministratorBeta. Quirky column widths in results display. No sorting, filtering. No import/export of queries or data. Queries saved to db table. Not updated since 0.8.3.2 (2006).
2021-07-18 unchanged
3
YYDB Browser for SQLiteVery limited. A basic browser. (that is an old review…)
2021-07-18 current v.3.12.2 for Windows & macOS released 2021-05-18
3?

I tend to use a combination of SQLite Expert Personal and SQLiteSpy when developing new queries. For using established queries, I rather prefer the look of the results tables from Spy but Expert handles user inputted parameters at run-time. For a new user, Spy is probably the easier of the two to start with. SQLite Expert Personal is better for its performance on very large databases, display of JPG blobs and the availability of a highly compatible substitute RMNOCASE collation.

Discussions & comments from Wikispaces site


ve3meo

Speed Reporting Complicated

ve3meo
14 January 2010 14:36:14

Evaluating speed has turned out to be more complicated than expected. The supposed speed regression after sqlite 3.6.17 is not exactly that. It seems that either the database design or the query design or both confuse the sqlite query optimiser into making sub-optimal choices of index files up to that version and different, worse ones after. That resulted in the necessity of using INDEXED BY and NOT INDEXED clauses to force the use of appropriate indexes, contrary to what the documentation instructs. As INDEXED was implemented with sqlite 3.6.3, older tools (SQLiteman, DBManager…) error out on the query but the later ones all execute at about the same speed (~3s).


ve3meo

ve3meo
11 March 2010 15:45:33

I should qualify these speed tests further and update them to reflect my best understanding. RM4’s NameTable has an index on the IsPrimary field. This seems to be a rather useless index because the field has only two values and thus cannot provide any speed improvement over a full scan. On the other hand, most searching of NameTable is against the OwnerID field; the corresponding index provides a tremendous speedup over a full scan. When a query uses IsPrimary as a condition in combination with a lookup of OwnerID, the query optimiser chooses the idxNamePrimary index with adverse consequences. Since the above posting, I have learned to hide the IsPrimary field from the query optimiser thus obviating the need for the INDEXED clauses and rendering the query compatible (in this respect) with the older SQLite implementations. It’s accomplished simply by prefacing the IsPrimary field with the ‘+’ operator. For example,

SELECT
Surname, Given, EventTable.Date AS BirthDate
FROM
EventTable
LEFT JOIN NameTable USING( OwnerID )
WHERE
OwnerType = 0 AND +NameTable.IsPrimary = 1
;

With the ‘+’ operator, EXPLAIN QUERY PLAN reports:
order from detail
0 0 TABLE EventTable
1 1 TABLE NameTable WITH INDEX idxNameOwnerID

Without the ‘+’ operator (or the INDEXED BY clause), it reports:
order from detail
0 0 TABLE EventTable
1 1 TABLE NameTable WITH INDEX idxNamePrimary


KenCRoy

Anyone have a preference for a free SQLite manager

KenCRoy
11 March 2010 18:13:19

Do any of you have a preference for a free SQLite Manager?

I really don’t want to spend any money until I really decide to convert to RootsMagic.

I tried SQLite Expert Personal — http://sqlite-expert-personal.software.informer.com/2.1/

but it won’t run the queries as posted on this forum.


ve3meo

ve3meo
11 March 2010 22:04:24

You can see by my ratings on this page that my rankings are:

1. SharpPlus SQLite Developer
2. SQLiteSpy
3. Tie between DBTools DBManager Standard and SQLiteman.

I would welcome others to add their ratings.

In practise, I use Developer the most because it is well-featured, robust, up-to-date (uses SQLite 3.6.22 – 23 just came out in the last couple of days), can sort and filter results on screen, etc., and may be the only one that will allow editing of all the tables. I use Spy often, because it shows results the fastest and maybe the nicest and is also pretty current (SQLite 3.6.21). Initially, my favourite was SQLiteman for easy, clean, fast with DBManager free edition as the candidate for development. Both of these are quite dated – the former no longer being actively supported and developed.

I have recently started exploring OpenOffice Base and Calc using an SQLite ODBC connection to the RootsMagic files. Using the latter is quite promising for filtering and sorting copied results and there is potential for formatted reporting, along the lines of what MarkVS id developing using MSAccess. I’m not so keen on using Base to develop complex queries as error reporting is pretty uninformative. But that may be just a reflection of being at the low end of the learning curve.

None of them are ideal and you may not want to pay the license fee for extra features. So I won’t recommend for you one over another but do advise you to avoid the ones I ranked low as I think you would waste your time trying them.

Inline comments


ve3meo

Comment: 1.9.0 supports loadable extensions wi…

ve3meo
05 June 2011 11:48:10

1.9.0 supports loadable extensions with potential for a RMNOCASE collation and RM date processing