[Tutor] How to create a sqlite table schema dynamically
Peter Otten
__peter__ at web.de
Thu Mar 20 22:56:53 CET 2014
Alan Gauld wrote:
> I confess I'm still not clear on your schema. What should the populated
> table(s) look like? It all feels very un-SQL like to me.
I'll make a bold guess that he wants to make a pivot table, something that
is indeed not supported by sqlite.
E. g., start with
week | os | installs
-------- | -------- | --------
2014-01 | redhat | 5
2014-01 | suse | 2
2014-02 | debian | 2
2014-02 | redhat | 7
2014-03 | suse | 3
2014-03 | ubuntu | 3
2014-03 | mint | 1
and wield it into something like
week | debian | mint | redhat | suse | ubuntu
-------- | -------- | -------- | -------- | -------- | --------
2014-01 | 0 | 0 | 5 | 2 | 0
2014-02 | 2 | 0 | 7 | 0 | 0
2014-03 | 0 | 1 | 0 | 3 | 3
Below is my attempt:
import sqlite3
db = sqlite3.connect(":memory:")
cs = db.cursor()
data = [
# week, os, installs
("2014-01", "redhat", 5),
("2014-01", "suse", 2),
("2014-02", "debian", 2),
("2014-02", "redhat", 7),
("2014-03", "suse", 3),
("2014-03", "ubuntu", 3),
("2014-03", "mint", 1),
]
def print_row(row, space=" "):
print(" | ".join(str(field).ljust(8, space) for field in row))
def show(sql):
first = True
for row in cs.execute(sql):
if first:
print_row(d[0] for d in cs.description)
print_row(("" for d in cs.description), "-")
first = False
print_row(row)
print("")
def sanitized(name):
"""Prevent SQL injection"""
if not name.isalpha(): # XXX a tad too rigid
raise ValueError("Illegal name {!r}".format(name))
return name
cs.execute("create table weekly_installs (week, os, installs);")
cs.executemany(
"insert into weekly_installs "
"(week, os, installs) values (?, ?, ?)", data)
show("select * from weekly_installs")
distros = sorted(
sanitized(distro) for [distro] in
cs.execute("select distinct os from weekly_installs"))
cs.execute("create table pivot (week, {})".format(
", ".join(d + " default 0" for d in distros)))
cs.executemany(
"insert into pivot (week) values (?)",
cs.execute("select distinct week from weekly_installs").fetchall())
for distro in distros:
update = "update pivot set {distro} = ? where week = ?"
update = update.format(distro=distro)
lookup = ("select installs, week from weekly_installs "
"where os = '{distro}'")
lookup = lookup.format(distro=distro)
cs.executemany(update, cs.execute(lookup).fetchall())
show("select * from pivot order by week")
OK, it still may serve as a bad example ;) Doing it in Python should be
much cleaner, but I'll leave that as an exercise...
More information about the Tutor
mailing list