1. 程式人生 > >Sqlite中的rowid欄位和integer primary key autoincrement的欄位區別

Sqlite中的rowid欄位和integer primary key autoincrement的欄位區別

前言

原創文章,歡迎轉載,請保留出處。
有任何錯誤、疑問或者建議,歡迎指出。
我的郵箱:[email protected]

Android中提供的SQLiteDatabase類,其中的幾個方法返回的是rowid,這個rowid並不是插入的行號(row num或者說是RecNo),而是sqlite中自動維護的一個隱藏的列rowid,這個rowid和integer primary key autoincrement的欄位有什麼區別呢?

Android中的資料庫查詢API

我們以Android中提供的資料庫插入API:db.insert來說明,這個方法的返回值描述如下:

Returns:
the
row ID of the newly inserted row, or -1 if an error occurred

經過驗證,這裡的row ID是是rowid,並不是插入的行號(row num或者說是RecNo)。下面我們假設integer primary key autoincrement的欄位的欄位名為id,如下圖:
返回的是rowid

RecNo和id:

RecNo和id

rowid和id:

rowid和id

但是這個rowid屬於由sqlite自己維護的列,如果不顯式指定,即使使用select * from table也是不會出現的。
如果要查詢rowid必須使用select rowid,* from table

RecNo和id區別

這個比較簡單,RecNo是單調遞增,無論資料表怎麼變化,只要查詢結果的第一條就是1(表頭為0),當然這個和表沒有任何關係,如果order by是由使用者決定的,所以不存在對應關係。
而id也是單調遞增的,如果刪除了某一條記錄,id還是會繼續遞增,不會調整,id屬於資料表的欄位,和資料有對應關係,無論怎麼查詢,id都不會變化。
比如select rowid,* from table order by id desc結果:
查詢結果
結論:RecNo就是查詢結果的一個標號而已。

rowid和id區別

這個rowid和每條資料是有密切關係的
比如select rowid,* from table order by id desc

結果:
查詢結果

我們參考sqlite官網提供說明:

The AUTOINCREMENT Keyword

If a column has the type INTEGER PRIMARY KEY AUTOINCREMENT then a slightly different ROWID selection algorithm is used. The ROWID chosen for the new row is at least one larger than the largest ROWID that has ever before existed in that same table. If the table has never before contained any data, then a ROWID of 1 is used. If the table has previously held a row with the largest possible ROWID, then new INSERTs are not allowed and any attempt to insert a new row will fail with an SQLITE_FULL error. Only ROWID values from previously transactions that were committed are considered. ROWID values that were rolled back are ignored and can be reused.

SQLite keeps track of the largest ROWID that a table has ever held using an internal table named “sqlite_sequence”. The sqlite_sequence table is created and initialized automatically whenever a normal table that contains an AUTOINCREMENT column is created. The content of the sqlite_sequence table can be modified using ordinary UPDATE, INSERT, and DELETE statements. But making modifications to this table will likely perturb the AUTOINCREMENT key generation algorithm. Make sure you know what you are doing before you undertake such changes.

The behavior implemented by the AUTOINCREMENT keyword is subtly different from the default behavior. With AUTOINCREMENT, rows with automatically selected ROWIDs are guaranteed to have ROWIDs that have never been used before by the same table in the same database. And the automatically generated ROWIDs are guaranteed to be monotonically increasing. These are important properties in certain applications. But if your application does not need these properties, you should probably stay with the default behavior since the use of AUTOINCREMENT requires additional work to be done as each row is inserted and thus causes INSERTs to run a little slower.

Note that “monotonically increasing” does not imply that the ROWID always increases by exactly one. One is the usual increment. However, if an insert fails due to (for example) a uniqueness constraint, the ROWID of the failed insertion attempt might not be reused on subsequent inserts, resulting in gaps in the ROWID sequence. AUTOINCREMENT guarantees that automatically chosen ROWIDs will be increasing but not that they will be sequential.

Because AUTOINCREMENT keyword changes the behavior of the ROWID selection algorithm, AUTOINCREMENT is not allowed on WITHOUT ROWID tables or on any table column other than INTEGER PRIMARY KEY. Any attempt to use AUTOINCREMENT on a WITHOUT ROWID table or on a column other than the INTEGER PRIMARY KEY column results in an error.

簡單抽取關鍵的內容就是:id如果設定為integer primary key autoincrement的欄位,則不需要自己手動賦值,插入時傳入null由資料庫來設定其值,這個值資料庫預設設定為rowid的最大值+1(也可以自己手動設定,但不要引起重複等問題)
rowid:單調遞增,直到達到最大值後,複用已經刪除的rowid作為新的值
id:可以自行設定,或者是資料庫自動設定(rowid的最大值+1),到達最大值後不復用已經刪除的值,拋異常SQLITE_FULL 。

這裡可以得出結論:rowid和id不一樣,不要混用。

特殊情況

如果integer primary key autoincrement的欄位名為rowid,那麼怎麼查詢rowid?
答案是相同的方法,rowid不是存在表中的,而是在sqlite_sequence中,如果查詢,則自己設定的rowid會起別名:
查詢結果

不查詢rowid則不會起別名:

查詢結果

相關推薦

Sqliterowidinteger primary key autoincrement區別

前言 原創文章,歡迎轉載,請保留出處。 有任何錯誤、疑問或者建議,歡迎指出。 我的郵箱:[email protected] Android中提供的SQLiteDatabase類,其中的幾個方法返回的是rowid,這個rowid並不是插入的行號(r

INTEGER PRIMARY KEY AUTOINCREMENT INTEGER PRIMARY KEY 區別

Sqlite 中INTEGER PRIMARY KEY AUTOINCREMENT和rowid/INTEGER PRIMARY KEY的使用 在用sqlite設計表時,每個表都有一個自己的整形id值作為主鍵,插入後能直接得到該主鍵. 因為sqlite內部本來

poj 2018_Best Cow Fences (求數列一個最大問題,的長度不小於L)

想要理解這個問題我們需要先掌握幾個要點: 1、對於一個序列,求一個欄位它的和最大,沒有“長度不小於L的限制”問題。 2、對於一個序列,求一個欄位它的和最大,欄位的長度不小於L的問題。 欄位和可以轉化成為字首和相減的形式,也就是說sumi=(a1+a2+...+ai)

SqliteINTEGER PRIMARY KEY的修正

在android的Sqlite 中對於INTEGER PRIMARY KEY, 如果插入資料A,B,C,它們的_id為1,2,3,那麼如果把他們都刪除了, 再插入一條資料,那麼它的id為為1而不是4。 因此我就寫了這個工具來生成id,它能讓生成相同的id相隔儘量的遠。然後在插據入數時手動設定id,及把這個作

SQLite的自增關鍵字:AUTO_INCREMENT、INTEGER PRIMARY KEYAUTOINCREMENT

1、SQLite不支援關鍵字AUTO_INCREMENT 1)AUTO_INCREMENT不生效的問題 SQL語句: CREATE TABLE todo (     id INTEGER AUTO_INCREMENT,     title TEXT,     PRI

快速重新整理物化檢視有with rowidwith primary key兩種,建立時該如何選擇?

 本文主要談及以下兩種物化檢視的應用:1、用於分散式環境裡的物化檢視,例如master table在A庫,B庫通過dblink建立了一個指向A庫taba的物化檢視mvb: create materialized view mvb ... as select * from

SQLServer有五種約束,Primary Key約束、Foreign Key約束、Unique約束、Default約束Check約束,今天使用SQL Server2008來演示下這幾種約束的

SQLServer中有五種約束,Primary Key約束、Foreign Key約束、Unique約束、Default約束和Check約束,今天使用SQL Server2008來演示下這幾種約束的建立和使用的方法。 1、Primary Key約束     在表中常有一列或多列的組合,其值能唯一標識表

MongoDB:16-MongoDB-索引陣列索引子文件

MongoDB允許深入文件內部,對巢狀欄位和陣列建立索引;巢狀物件和陣列欄位可以和複合索引中的頂級欄位一起使用,多數情況下與“正常”索引欄位的行為也是一致的。考慮以下文件集合(use

區分Sqlite的B-樹B+樹——索引儲存

在網上看一些帖子的時候。發現有人說Sqlite中組織管理資料庫檔案儲存的機制為B-樹。 本人覺著這麼說非常的不嚴謹。 於是本人翻出了《the definitive guide to sqlite》SECOND EDITON。經過再次查閱,想在這裡總結一下。 在Sql

FreeMarker<#include><#import>標簽的區別

str 使用 名稱 clas -m log rect 兩個 arc 在使用freemarker作為前端頁面模板的應用中,會有很多的freemarker模板頁面,這些ftl

java類變量實例變量的實質區別

tar com 對象共享 第一章 let 空間 ref size 對象 類變量和實例變量的區別 相對於static(靜態的)或說類的, 本章開始提到的都是instance(實例的)或說對象的。 每個對象都有自己的一份兒對象域或實例域,相互之間沒關系, 不共享。 我們可以從對

大資料,機器學習資料探勘的聯絡與區別

資料探勘是從海量資料中獲取有效的、新穎的、潛在有用的、最終可理解的模式的非平凡過程。 資料探勘中用到了大量的機器學習界提供的資料分析技術和資料庫界提供的資料管理技術。 從資料分析的角度來看,資料探勘

.Net HashTable,HashMap Dictionary《key,value》List《T》DataTable的比較

參考資料http://www.coding123.net/article/20120419/DataTable-IList-compare.aspx首先:(ling)在.Net  模仿java 的過程中   拋棄了 HashMap ,所以以後再去面試.Net的時候當別人問你H

Eclipse工程Java Build Path的JDK版本Java Compiler Compiler compliance level的區別(轉)

在這裡記錄一下在eclipse中比較容易搞混淆和設定錯誤的地方。如下圖所示的功能: 檢視原圖 最精準的解釋如下: Build Path是執行時環境  Compiler是編譯時環境  假設,你的程式碼用到泛型,Build Path環境為1.5,Compil

phpprint_r、var_dumpvar_export幾個函式的用法區別 。php setcookie一些限制。php不同路徑cookies取值問題。PHP獲取站點根目錄

php中print_r、var_dump和var_export幾個函式的用法區別   print_r ( $array/$var )  print 是列印的意思,而r則取自Array的單詞,那麼該函式的功能就是列印陣列內容,它既可以列印陣列內容,也可以列印普通的變數

C++關於[]靜態陣列new分配的動態陣列的區別分析

五、通過函式返回一個數組的問題    函式宣告的靜態陣列不可能通過函式返回,因為生存期的問題,函式呼叫完其內部變數佔用的記憶體就被釋放了。如果想通過函式返回一個數組,可以在函式中用new動態建立該陣列,然後返回其首地址。 其原因可以這樣理解,因為[]靜態陣列是在棧中申請的,而函式中的區域性變數也是在棧中的,而

python靜態方法(@staticmethod)類方法(@classmethod)的區別

方法 屬性方法 參數 pre 如果 icm ssm 使用 類方法 一般來說,要使用某個類的方法,需要先實例化一個對象再調用方法。 而使用@staticmethod或@classmethod,就可以不需要實例化,直接類名.方法名()來調用。 這有利於組織代碼,把某些應該屬於某

c#字典傳入結構體類在賦值時候的區別

//我以為這裡可以和c++中的map一樣,可以直接賦值,但是會報錯 //這裡不能這樣直接賦值 //然後我是用方法1中那種方式處理的,但我感覺這麼處理很麻煩 //然後我在csdn論壇上問了下,然後我換成方法2,這種方法可以直接賦值,不再那麼繁瑣 //可以說是各有各的好處吧

資料庫使用外來鍵不使用外來鍵有什麼區別

今天聽了一個企業技術總監的宣講,結果聽說在他開發系統的過程中,都沒有用到外來鍵,這讓我很驚訝,趕緊上網搜尋了一些資料看了看,終於明白了不用外來鍵的原因。 這是一篇關於是否使用外來鍵的討論,講的很有道理: 對於主/外來鍵/索引來說,在一些開發團隊中被認為是處理資料庫關係的利

將oracle表名全部修改為小寫

在建立表和表結構的時候,如果想要小寫需要在名稱上面新增雙引號,如果不新增oracle資料庫會預設識別為大寫 1.將表名和欄位名改為大寫 批量將表名變為大寫 begin    for c in (select table_name tn from user_tabl