SQLite C/C++接口簡介

jopen 9年前發布 | 18K 次閱讀 SQLite 數據庫服務器

原文  http://segmentfault.com/a/1190000002771737

翻譯自 https://www.sqlite.org/cintro.html ,建議閱讀原文

摘要

接下來的兩個對象和八個方法包含了SQLite接口的基本要素:

簡介

早期的SQLite只支持五個C/C++接口,所以非常容易學習。但是隨著SQLite的不斷壯大,新的C/C++接口不斷加入,目前已有超過 200個不同的接口。這能輕易壓倒一個新手程序員。幸運的是,大部分SQLite的C/C++接口非常專業并且你不需要去關心。盡管有如此多的切入 點,SQLite的核心API依然比較簡單易于學習,易于編程。這篇文章旨在提供所有必需的背景信息以便于讓你理解SQLite是如何工作的。

這份單獨的文檔, SQLite C/C++接口 ,提供了所有SQLite C/C++ 接口的詳細說明。當讀者理解了SQLite操作的基本原則,這份文檔可以作為參考指南使用。本文章目的僅僅是介紹,而不是SQLite API 的完整或者權威的指南。

核心對象和接口

SQL數據庫引擎的主要任務是執行SQL語句。為了實現這個目的,開發者需要知道這兩個對象:

嚴格得講,有了便捷的包裝接口預編譯語句對象,sqlite3_exec 或者 sqlite3_get_table之后, 預編譯語句 對象不再是必須的。因為可以使用這些便捷的包裝器封裝和隱藏 預編譯語句 對象。但是要充分利用SQLite需要理解預編譯語句對象。

數據庫連接預編譯語句 對象是由以下列出的一部分接口控制:

這六個C/C++接口程序和上述的兩個對象來自于SQLite基礎功能的核心。理解了它們,開發者將能更好得使用SQLite。

請注意上述的程序是概念性的而不是實際上的。這些程序大都存在多個版本。比如上面列表只顯示了單個名為 sqlite3_open() 的程序,但實際上有三個獨立的程序以不同的方式完成同樣的事情: sqlite3_open() , sqlite3_open16()sqlite3_open_v2() 。另外列表里還提及了 sqlite3_column() ,但實際上并沒有這樣的程序存在。列表中顯示的"sqlite3_column()"代表的是這個程序整個家族,它們被用于提取不同類型的列數據。

這里總結一下核心接口會做什么:

  • sqlite3_open() 用來打開一個數據庫文件的連接并返回數據庫連接對象。這通常是應用調用的第一個SQLite API,低于大多數其他的SQLite API這是先決條件。許多SQLite接口需要一個指向數據庫連接的指針作為第一個參數,也可以認為是數據庫連接對象的方法。 sqlite3_open()是數據庫連接對象的構造方法。

  • sqlite3_prepare() 將SQ文本轉換為預編譯語句對象并返回該對象的指針。這個接口需要一個由sqlite3_open()創建的指向數據庫連接的指針和一段包含SQL語句的文本。這個API并非真正得執行SQL語句,僅僅準備需要執的SQL語句。

    把每條SQL語句想象成一個小的計算機程序。sqlite3_prepare()的目的是將程序編譯成目標代碼。預編譯語句是目標代碼。接著sqlite3_step()接口運行目標代碼并得到結果。

請注意對于新的應用不建議使用sqlite3_prepare(),而應使用架構更新的程序sqlite3_prepare_v2()代替。

  • sqlite3_step() 用來執行之前由sqlite3_prepare()接口創建的預編譯語句。這語句執行到第一行可用的位置。若要執行結果的第二行,需要再次調用 sqlite3_step()。繼續調用 sqlite3_step()直到語句結束。對于那些不返回結果的語句(比如: INSERT, UPDATE, 或者DELETE),只需調用一次sqlite3_step()。

  • sqlite3_column() 從sqlite3_step()執行的準備語句得到的結果集的當前行中返回一個列。每次sqlite3_step()得到一個結果集的列后,這個過程就可 以被多次調用去查詢這個行的各列的值。正如上面提到的那樣,在SQLite API中并沒有這個一個"sqlite3_column()"函數。取而代之的是整個 "sqlite3_column()"家族,用于返回不同數據類型的結果。在這個家族里也有函數用來返回結果的大小(如果類型是string或者 BLOB)和結果集列的數量。

      - sqlite3_column_blob()

    • sqlite3_column_bytes()
    • sqlite3_column_bytes16()
    • sqlite3_column_count()
    • sqlite3_column_double()
    • sqlite3_column_int()
    • sqlite3_column_int64()
    • sqlite3_column_text()
    • sqlite3_column_text16()
    • sqlite3_column_type()
    • sqlite3_column_value()</pre> </li>
          <li>
              <p>
                  <a href="/misc/goto?guid=4959632414692213299">sqlite3_finalize()</a> 銷毀由sqlite3_prepare()創建的預編譯語句。為了防止內存泄露,每條預編譯語句必須調用這個方法進行銷毀。
              </p>
          </li>
          <li>
              <a href="/misc/goto?guid=4959632415268555047">sqlite3_close()</a> 關閉由sqlite3_open()創建的數據庫連接。在關閉連接之前,所有的預編譯語句都應該被finalize。
          </li>
      </ul>
      <h2>
          核心程序和接口的典型用法
      </h2>
      <p>
          應用若要使用SQLite通常的做法是在初始化的時候通過sqlite3_open()創建單個數據庫連接。注意sqlite3_open()
      
      可以用來打開存在的數據庫文件也能創建新的數據庫文件。盡管很多的應用僅僅使用單個數據庫連接時,但也沒有任何理由不能多次調用 sqlite3_open()創建多個數據庫連接,同一個數據庫或者不同的數據庫。多線程的應有時會為每個線程創建不同的數據庫連接。還要注意,沒有必要 為了訪問兩個或者多個數據庫而創建不同的數據庫連接。單個數據庫連接可以使用 ATTACH SQL命令同時訪問兩個或者多個數據庫。
      </p>
      <p>
          大多數應用的做法是在關閉時調用sqlite3_close()銷毀數據庫連接。或者例如一個應用使用SQLite作為文件格式,在文件/打開菜單操作時打開數據庫連接,在文件/關閉菜單時銷毀相應的數據庫連接。
      </p>
      <p>
          若要運行SQL語句,請遵循以下步驟:
      </p>
      <ul>
          <li>
              使用 <a href="/misc/goto?guid=4959632414615686124">sqlite3_prepare()</a> .創建預編譯語句對象。
          </li>
          <li>
              調用 <a href="/misc/goto?guid=4959632415070024313">sqlite3_step()</a> 一次或者多次執行預編譯語句對象
          </li>
          <li>
              對于查詢來說,調用 <a href="/misc/goto?guid=4959632415156075912">sqlite3_column()</a> 提取執行 <a href="/misc/goto?guid=4959632415070024313">sqlite3_step()</a> 得到的結果集
          </li>
          <li>
              使用 <a href="/misc/goto?guid=4959632414692213299">sqlite3_finalize()</a> 來銷毀預編譯語句
          </li>
      </ul>
      <p>
          為了更加有效得使用SQLite,以上是需要了解的。剩下的就只有細枝末節。
      </p>
      <h2>
          方便的包裝器
      </h2>
      <p>
          <a href="/misc/goto?guid=4959632415365663143">sqlite3_exec()</a> 接口是一個方便的包裝器,調用一個方法便可執行上面的四個步驟。傳遞到 <a href="/misc/goto?guid=4959632415365663143">sqlite3_exec()</a> 中的回調函數將用于處理每行結果集。 <a href="/misc/goto?guid=4959632415868753296">sqlite3_get_table()</a> 是另一個方便的包裝器,同樣可以用上述的四個步驟。與 <a href="/misc/goto?guid=4959632415365663143">sqlite3_exec()</a> 不同的是, <a href="/misc/goto?guid=4959632415868753296">sqlite3_get_table()</a> 將結果存儲在堆存儲器里而非調用回調函數。
      </p>
      <p>
          無論是 <a href="/misc/goto?guid=4959632415365663143">sqlite3_exec()</a> 還是 <a href="/misc/goto?guid=4959632415868753296">sqlite3_get_table()</a> 做的任何事情都可以由核心程序來完成,認識到這一點很重要。事實上,這些包裝器僅僅實現了核心程序。
      </p>
      <h2>
          綁定參數與重用預編譯語句
      </h2>
      <p>
          在之前的討論中,假設了每條SQL語句只準備,執行了一次然后銷毀。但是SQLite允許相同的預編譯語句執行多次。這由以下的程序完成:
      </p>
      <ul>
          <li>
              <a href="/misc/goto?guid=4959632415980635367">sqlite3_reset()</a> 
          </li>
          <li>
              <a href="/misc/goto?guid=4959632414889727077">sqlite3_bind()</a> 
          </li>
      </ul>
      <p>
          在 <a href="/misc/goto?guid=4959632414521437674">預編譯語句</a> 被一次或多次調用 <a href="/misc/goto?guid=4959632415070024313">sqlite3_step()</a> 執行之后,它可以通過調用 <a href="/misc/goto?guid=4959632415980635367">sqlite3_reset()</a> 重置以便于再次執行。對已存在的預編譯語句對象使用 <a href="/misc/goto?guid=4959632415980635367">sqlite3_reset()</a> 而不是創建一個新的預編譯語句,避免不必要得調用 <a href="/misc/goto?guid=4959632414615686124">sqlite3_prepare()</a> 。對于很多SQL語句來說,執行sqlite3_prepare()的時間等于或者超過執行sqlite3_step()的時間。所以避免調用sqlite3_prepare()可以顯著提升性能。
      </p>
      <p>
          通常情況下,盡管多次執行相同的SQL語句并非有用。更多時候,執行的是相似的語句。比如你可能想要多次執行一條插入語句,但插入的值不同。為
      
      了使用這類的靈活性,SQLite允許將要執行的SQL語句包含之前綁定的參數。這些值可以在后面更改,這樣相同的預編譯語句可以使用新的值執行第二次。
      </p>
      <p>
          在SQLite中,無論是否有效得包含字符串,都可以選取以下的形式作為參數:
      </p>
      <ul>
          <li>
              ?
          </li>
          <li>
              ?NNN
          </li>
          <li>
              :AAA
          </li>
          <li>
              $AAA
          </li>
          <li>
              @AAA
          </li>
      </ul>
      <p>
          在上面的例子中,NNN是整數值,AAA是標識符。參數初始化值為NULL。首先先調用 <a href="/misc/goto?guid=4959632415070024313">sqlite3_step()</a> 或者在 <a href="/misc/goto?guid=4959632415980635367">sqlite3_reset()</a> 立即調用。應用可以調用其中一個sqlite3_bind()接口附加到參數上。每次調用 <a href="/misc/goto?guid=4959632414889727077">sqlite3_bind()</a> 將覆蓋先前的參數綁定。
      </p>
      <p>
          應用程序可以提前準備多條SQL語句,并根據需要對其執行。對于準備的語句在數量上沒有任何限制。
      </p>
      <h2>
          配置SQLite
      </h2>
      <p>
          對于大多數應用來說SQLite的默認配置已經足夠了。但是有時開發者想要調整設,以盡量提升一點性能,或者使用一些不起眼的特性。
      </p>
      <p>
          <a href="/misc/goto?guid=4959632416165658055">sqlite3_config()</a> 接口用于創建SQLite全局的,進程級的配置更改。在任何數據庫連接被創建前,sqlite3_config()接口必須被調用。 <a href="/misc/goto?guid=4959632416165658055">sqlite3_config()</a> 接口允許程序員做這樣的事情:
      </p>
      <ul>
          <li>
              調整SQLite內存分配,包括為實時嵌入系統設置內存分配器和設置應用定義的 <a href="/misc/goto?guid=4959632416259138569">內存分配器</a> 。
          </li>
          <li>
              設置進程級的 <a href="/misc/goto?guid=4959632416344874016">錯誤日志</a> 
          </li>
          <li>
              指定應用定義的頁面緩存
          </li>
          <li>
              調整互斥體使之適合于不同的 <a href="/misc/goto?guid=4959632416429663000">線程模型</a> ,或者替換應用定義的互斥系統 <br />
      
      進程級的配置完成之后 數據庫連接 便會建立。個別的數據庫連接可以調用 sqlite3_limit()sqlite3_db_config() 進行配置。
          </li>
      </ul>
      <h2>
          擴展SQLite
      </h2>
      <p>
          SQLite還包括了用來擴展功能的接口,這些程序包括:
      </p>
      <ul>
          <li>
              <a href="/misc/goto?guid=4959632416683597006">sqlite3_create_collation()</a> 
          </li>
          <li>
              <a href="/misc/goto?guid=4958539522935969758">sqlite3_create_function()</a> 
          </li>
          <li>
              <a href="/misc/goto?guid=4959632416793951857">sqlite3_create_module()</a> 
          </li>
          <li>
              <a href="/misc/goto?guid=4959632416884363124">sqlite3_vfs_register()</a> 
          </li>
      </ul>
      <p>
          sqlite3_create_collation()接口用來為排序文本創建新的排序序列。 <a href="/misc/goto?guid=4959632416793951857">sqlite3_create_module()</a> 接口用來注冊新的 <a href="/misc/goto?guid=4959632416970123841">虛擬表</a> 實現。 <a href="/misc/goto?guid=4959632416884363124">sqlite3_vfs_register(</a> )接口創建新的 <a href="/misc/goto?guid=4959632417077983889">VFSes</a> 。
      </p>
      <p>
          <a href="/misc/goto?guid=4958539522935969758">sqlite3_create_function()</a> 接口創建新的SQL功能 - 無論是標量還是聚合。新功能的實現通常使用了以下幾個附加接口:
      </p>
      <ul>
          <li>
              <a href="/misc/goto?guid=4959632417169147416">sqlite3_aggregate_context()</a> 
          </li>
          <li>
              <a href="/misc/goto?guid=4959632417243730767">sqlite3_result()</a> 
          </li>
          <li>
              <a href="/misc/goto?guid=4959632417331880171">sqlite3_user_data()</a> 
          </li>
          <li>
              <a href="/misc/goto?guid=4959632417409568784">sqlite3_value()</a> 
          </li>
      </ul>
      <p>
          SQLite所有內置的SQL函數正式使用這些接口來創建的。參考SQLite源碼,特別是date.c和func.c源文件的例子。
      </p>
      <p>
          共享的庫或 Dll 可以用作 SQLite 的 <a href="/misc/goto?guid=4958539522300076698">可加載擴展</a> 。
      </p>
      <h2>
          其他接口
      </h2>
      <p>
          這篇文章僅僅提及了SQLite接口的基礎功能。SQLite庫還包含了很多其他有用的特性但是這里沒有描述。你能在 <a href="/misc/goto?guid=4959632415483783314">C/C++接口規范</a> 中找到SQLite完整的功能列表。請參閱關于SQLite所有接口的權威文檔。
      </p>
      
      </div> </div>
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!