2016-09-24 10 views
1

Was bewirkt die folgende SQL-Anweisung im Fall von SQLite?Funktionsweise des benutzerdefinierten Datentyps in SQLite

CREATE TABLE foo(id INTEGER PRIMARY KEY, time STRFTIME); 

Beachten Sie, dass die time Spalte den STRFTIME Typ hat, die nicht in der documentation aufgeführt ist.

Ich denke, dass die folgende INSERT Arbeiten ohne Fehler

sqlite> INSERT INTO foo (time) VALUES('text'); 
sqlite> SELECT * FROM foo; 
1|text 

aus diesem Grund:

3,1. Bestimmung der Säule Affinity

Die Affinität einer Spalte wird durch den deklarierten Typ der -Säule bestimmt, gemäß den folgenden Regeln in der angegebenen Reihenfolge:

  1. Wenn der deklarierte Typ enthält die Zeichenfolge „INT "Dann wird ihm INTEGER-Affinität zugewiesen.

  2. Wenn der deklarierte Typ der Spalte einen der Zeichenfolgen "CHAR", "CLOB" oder "TEXT" enthält, dann hat diese Spalte die TEXT-Affinität. Beachten Sie, dass der Typ VARCHAR die Zeichenfolge "CHAR" enthält und daher TEXT Affinität zugewiesen ist.

  3. Wenn der deklarierte Typ für eine Spalte die Zeichenfolge "BLOB" enthält oder wenn kein Typ angegeben ist, hat die Spalte Affinität BLOB.

  4. Wenn der deklarierte Typ für eine Spalte einen der Zeichenfolgen "REAL", "FLOA" oder "DOUB" enthält, hat die Spalte die REAL-Affinität.

5. Ansonsten ist die Affinität ZIFFERN.

und diese:

Eine Spalte mit NUMERIC-Affinität kann Werte mit allen fünf Speicherklassen enthalten. Wenn Textdaten in eine NUMERIC-Spalte eingefügt werden, wird die Speicherklasse des Texts in INTEGER oder REAL (in der Reihenfolge Präferenz) konvertiert, wenn eine solche Konvertierung verlustfrei und reversibel ist. Bei Konvertierungen zwischen TEXT- und REAL-Speicherklassen berücksichtigt SQLite die Konvertierung als verlustfrei und reversibel, wenn die ersten 15 signifikanten Dezimalziffern der Zahl beibehalten werden. Wenn die verlustfreie Konvertierung von TEXT in INTEGER oder REAL nicht möglich ist, wird der Wert mit der Speicherklasse TEXT gespeichert. Es wird kein Versuch gemacht NULL oder BLOB-Werte I

Am Recht zu konvertieren?

Antwort

1

Ja; STRFTIME hat genau die gleiche Affinität wie FLUFFY BUNNIES, d.h. numerisch.

0

Wenn Sie einen neuen Typ implementieren möchten, muss er intern in einem der sqlite primitiven Typen gespeichert werden. Sie müssen dann Funktionen bereitstellen, um von Python zu SQLite und umgekehrt zu konvertieren.

Hier sind die Schritte ausführen:

  • Verwenden sqlite3.register_adapter angeben, wie Python Typ zu konvertieren SQLite. Obwohl Sie in einen der internen/primitiven SQLite-Typen (text, integer, real, blob und null) konvertieren könnten, sollten Sie TEXT verwenden, um zurück konvertieren zu können (siehe nächster Punkt).
  • Verwenden Sie sqlite3.register_converter, um anzugeben, wie Sie von der internen SQLite-Repräsentation zurück in den Python-Typ konvertieren.
  • Geben Sie beim Aufruf connect() das Argument detect_types=sqlite3.PARSE_DECLTYPES an.
  • Wenn Sie eine Tabelle erstellen, verwenden Sie den benutzerdefinierten Typnamen.

Hinweis: die register_converter Dokumentation besagt, dass Sie aus einem Byte-String konvertieren müssen.

Hier ein Beispiel ist eine benutzerdefinierte ‚date‘ Art zu implementieren:

import sqlite3 
from datetime import date 

def date_to_str(d): # for python to sqlite 
    return '%04d%02d%02d' % (d.year, d.month, d.day) 
def str_to_date(s): # for sqlite to python 
    y=int(s[0:4]) 
    m=int(s[4:6]) 
    d=int(s[6:8]) 
    return date(y,m,d) 

sqlite3.register_adapter(date,date_to_str) 
sqlite3.register_converter('date',str_to_date) 

WEEKDAYS = { 
    0: "Mon", 1: "Tue", 2: "Wed", 3: "Thu", 4: "Fri", 5:"Sat",6:"Sun" 
} 
def test(): 
    s = sqlite3.connect('myfile.dat', detect_types=sqlite3.PARSE_DECLTYPES) 
    c = s.cursor() 
    c.execute('create table t1(id integer primary key, d1 date)') 
    c.execute('insert into t1 values(?,?)', (1, date(2016,9,24))) 
    c.execute('insert into t1 values(?,?)', (2, date(2000,1,1))) 
    s.commit() 
    for r_id, r_date in c.execute('select id,d1 from t1 order by d1'): 
    print r_id, r_date, r_date.year, r_date.month, r_date.day, WEEKDAYS[r_date.weekday()] 


if __name__ == '__main__': 
    test() 

Während ich tippe meine Antwort, ich las die akzeptierte Antwort, und erkennen, das war nicht Ihre Frage. Wenn dies jedoch anderen Menschen helfen kann ...

Verwandte Themen