Programmera SQLite i C Tutorial Two

Denna handledning är den andra i en serie om programmering av SQLite i C.

SQLite lagrar en samling tabeller i en enda fildatabas, som vanligtvis slutar på .db. Varje tabell är som ett kalkylblad, den består av ett antal kolumner och varje rad har värden.

Om det hjälper, tänk på varje rad som en struktur, med kolumnerna i tabellen som motsvarar fälten i strukturen.

En tabell kan ha så många rader som passar på en disk. Det finns en övre gräns men dess enorma 18 446 744 073 709 551 616 för att vara exakt.

En tabell kan ha upp till 2 000 kolumner eller om du kompilerar om källan kan du maximera den till fantastiska 32.767 kolumner.

SQLite API

För att kunna använda SQLite måste vi ringa till API: et. Du hittar en introduktion till detta API på den officiella webbplatsen Introduktion till SQLite C / C ++. Det är en samling funktioner och enkla att använda.

Först behöver vi ett handtag till databasen. Detta är av typen sqlite3 och returneras av ett samtal till sqlite3_open (filnamn, ** ppDB). Efter det kör vi SQL.

Låt oss dock ha en liten försämring först och skapa en användbar databas och några tabeller med SQLiteSpy. (Se tidigare handledning för länkar till den och SQLite-databasbläsaren).

Händelser och arenor

Databasen about.DB kommer att innehålla tre tabeller för att hantera evenemang på flera platser. Dessa evenemang kommer att vara fester, diskotek och konserter och kommer att äga rum på fem arenor (alpha, beta, charlie, delta och echo). När du modellerar något liknande, hjälper det ofta att börja med ett kalkylblad. För enkelhets skull lagrar jag bara ett datum inte en tid.

Kalkylarket har tre kolumner: Datum, plats, händelsetyp och ungefär tio händelser som detta. Datum går från 21 till 30 juni 2013.

Nu har SQLite ingen uttrycklig datumtyp, så det är lättare och snabbare att lagra det som ett int och på samma sätt som Excel använder datum (dagar sedan 1 januari 1900) har int-värden 41446 till 41455. Om du lägger datumen i ett kalkylblad formatera sedan datumkolumnen som ett nummer med 0 decimaler, det ser ut så här:

Nu kan vi lagra dessa data i en tabell och för ett så enkelt exempel skulle det antagligen vara acceptabelt. Men god databasdesign kräver viss normalisering.

Unika dataobjekt som arenatyp ska finnas i sin egen tabell och händelsetyperna (fest osv.) Bör också finnas i en. Slutligen, eftersom vi kan ha flera händelsetyper på flera platser, (ett förhållande många till många) behöver vi en tredje tabell för att hålla dessa.

De tre borden är:

  • arenor - innehar alla fem arenor
  • eventtyper - innehåller alla tre händelsetyper
  • händelser - innehar datum plus plats-id plus evenemangstyp-id. Jag har också lagt till ett beskrivningsfält för detta evenemang, t.ex. "Jim's Birthday".

De två första tabellerna innehåller datatyperna så att platser har namn alfa till eko. Jag har också lagt till ett heltal-id och skapat ett index för det. Med det lilla antalet arenor (5) och händelsetyper (3) kan det göras utan index, men med större tabeller kommer det att bli mycket långsamt. Så varje kolumn som troligen kommer att sökas på, lägg till ett index, helst heltal

SQL för att skapa detta är:

Indexet på händelsetabellen har datum, id-händelse, händelsetyp och plats. Det betyder att vi kan fråga händelsetabellen för "alla evenemang på ett datum", "alla evenemang på en plats", "alla fester" etc och kombinationer av sådana som "alla fester på en plats" osv..

Efter att ha kört SQL-tabellfrågor skapas de tre tabellerna. Observera att jag har lagt all den sql i textfilen create.sql och den innehåller data för att fylla några av de tre tabellerna.

Om du sätter; i slutet av linjerna som jag har gjort i create.sql så kan du batcha och utföra alla kommandon på en gång. Utan ; du måste köra var och en av sig själv. I SQLiteSpy, klicka bara på F9 för att köra allt.

Jag har också inkluderat sql för att släppa alla tre tabellerna i flera radskommentarer med / * ... * / samma som i C. Välj bara de tre raderna och gör ctrl + F9 för att köra den markerade texten.

Dessa kommandon infogar de fem arenorna:

Återigen har jag inkluderat kommenterad text till tomma tabeller med ta bort från rader. Det finns ingen ångring så var försiktig med dessa!

Otroligt nog, med all information som laddats (visserligen inte mycket) är hela databasfilen på disken bara 7KB.

Händelsedata

Istället för att bygga upp ett gäng med tio infoga uttalanden, använde jag Excel för att skapa en .csv-fil för händelsedata och använde sedan kommandoradssystemet SQLite3 (som kommer med SQLite) och följande kommandon för att importera den.

Obs: Varje rad med ett prefix för period (.) Är ett kommando. Använd .help för att se alla kommandon. För att köra SQL skriver du bara in det utan någon prefix.

Du måste använda dubbla svartstänk \\ i importvägen för varje mapp. Gör endast den sista raden efter .importen har lyckats. När SQLite3 körs är standardseparatorn a: så den måste ändras till komma före importen.

Tillbaka till koden

Nu har vi en fullbefolkad databas, låt oss skriva C-koden för att köra denna SQL-fråga som returnerar en lista med parter, med beskrivning, datum och platser.

  • Är du ny på SQL? Läs Vad är SQL?

Detta gör en koppling med kolumnen idvenue mellan evenemangs- och arenatabellen så att vi får namnet på arenan inte dess int idvenue-värde.

SQLite C API-funktioner

Det finns många funktioner men vi behöver bara en handfull. Behandlingsordningen är:

  1. Öppna databasen med sqlite3_open (), avsluta om fel har öppnats.
  2. Förbered SQL med sqlite3_prepare ()
  3. Slinga med slqite3_step () tills det inte finns fler poster
  4. (I loopen) bearbeta varje kolumn med sqlite3_column ...
  5. Ring slutligen sqlite3_close (db)

Det finns ett valfritt steg efter att ha ringt sqlite3_prepare där alla passerade parametrar är bundna men vi sparar det för en framtida tutorial.

Så i programmet som listas nedan är pseudokoden för de viktigaste stegen:

SQL returnerar tre värden så om sqlite3.step () == SQLITE_ROW kommer värdena att kopieras från lämpliga kolumntyper. Jag har använt int och text. Jag visar datumet som ett nummer men kan gärna konvertera det till ett datum.

Lista med exempelkod