Is a PK required for GeoPackage vector layers?

Every feature table in GeoPackage must have a primary key of type INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL. See section 2.1.6 in the standard or this part in the getting started document http://www.geopackage.org/guidance/getting-started.html#features

User-defined Data Tables

Features are stored in user-defined data tables. Each features table has exactly one geometry column, a BLOB. (The structure of this BLOB is described here.) The OGC Simple Features geometry types are the supported geometry types. Other than the geometry column and a primary key, the schema of a features table is up to the implementer. Properties (text, integer, or real) provide additional information about each feature. The GeoPackage standard has an example schema.

The user interface of QGIS made you to believe that you created a table without primary key when you removed text fid from the "FID" field in the dialog. However, even if you do that the table will still be created with a primary key but the PK field will just have no name. You can see the whole CREATE TABLE sentense from the internal tables of SQLITE with a query

SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'test_table'

The result is like this:

CREATE TABLE "test_table" ( "" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
"geom" MULTISURFACE, "ogr_pkid" TEXT(255), "id" TEXT(255));

QGIS creates the table in this way so that the mandatory part "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL" will be found from the schema of the table as GeoPackage standard requires. However, SQLite creates such PK field in any case if a user does not explicitly deny it. Internally SQLite knows that field as ROWID https://www.sqlite.org/rowidtable.html.

QGIS does not show the ROWID field that really exists for the SQLite engine. Therefore it might be better if you do not leave the name of the FID field empty but give it an alias like "foo" or "fid2". Then the table will be created as CREATE TABLE "test_table" ( "foo" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,... and the "foo" field will be visible in QGIS.


See GeoPackage Encoding Standard Section 2.1.6. Requirement 29 say that there should be an explicit primary key. Clients must support views that cannot have a primary key. But if you do, the SQL commandVACUUM can change the key values of your features.