1

I have a list of tuples like so:

>>> all_names = c.execute("""select name from fb_friends""")
>>> for name in all_names:
...     print(name)
('Jody Ann Elizabeth Lill',)
('Georgia Gee Smith',)
...(282 more)...
('Josh Firth',)
('Danny Hallas',)

And I want to create a table for each individual person. First I need to replace all spaces with an underscore in order to be SQLite3 table names, so I do that like so:

>>> all_names = c.execute("""select name from fb_friends""")
>>> for name in all_names:
...     friends_name = name[0].replace(" ", "_")
...     print(friends_name)
Jody_Ann_Elizabeth_Lill
Georgia_Gee_Smith
...(282 more)...
Josh_Firth
Danny_Hallas

So if I understand correctly I now have a list, not a list of tuples..? Which should be simple to create all my tables from this list like so:

>>> all_names = c.execute("""select name from fb_friends""")
>>> for name in all_names:
...     friends_name = name[0].replace(" ", "_")
...     c.execute("""create table {0} (`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `work` TEXT NOT NULL, `education` TEXT, `current_city` TEXT, `phone_number` TEXT, `dob` TEXT, `gender` TEXT, `sexual_orientation` TEXT, `religion` TEXT, `relationship_status` TEXT, `about_me` TEXT )""".format(friends_name))

But all it does is create a table from the first name in the list, I would have thought the for loop would iterate over the list of names and create a table for each one, which is what I want, can people please advise me on a few things:

  1. Is using the .replace method the best way to get the underscores in the names? If no then what is?
  2. Why is the for loop not iterating over each name to create the tables? And how do I make it do that?
  3. Are my methods correct at all? If not then what methods would do it better?
Ébe Isaac
  • 11,563
  • 17
  • 64
  • 97
Jamie Lindsey
  • 928
  • 14
  • 26
  • what does 'all_names' variable look like before you iterate through it with your for loop? – matias elgart Nov 13 '16 at 15:20
  • its an sqlite3.Cursor objectso I need to iterate to get anything from it don't i ? – Jamie Lindsey Nov 13 '16 at 15:38
  • `>>> all_names = c.execute("""select name from fb_friends""") >>> print(all_names) ` – Jamie Lindsey Nov 13 '16 at 15:39
  • try: list(all_names) i'm asking for you to show what you're iterating over before you jump into the loop, since the loop only seems to be iterating once. in other words, are you sure all_names has many entries to iterate over? another way to test would be to comment out the c.execute() call and just put a print statement with the name. – matias elgart Nov 13 '16 at 15:39
  • 3
    *I want to create a table for each individual person*...in the database world, this is highly ill-advised as it strays from third-norm relational model. Plus, this can be a runaway script as *fb_friends* can grow to hamper a database quickly. Why build 280+ tables of same structure? Simply use one person table with *name* as a field. Querying will be vastly easier and this scales efficiently. – Parfait Nov 13 '16 at 15:56
  • @melgart [('Jody Ann Elizabeth Lill',), ('Georgia Gee Smith',),...('Josh Firth',), ('Danny Hallas',)], sorry my brains not working very well today :/ – Jamie Lindsey Nov 13 '16 at 16:24
  • @JackHerer i would have to agree with Parfait's comments above -- creating a new table _per_ user will not scale very well. a single 'user' table with one row for each person is a more resource-friendly way to model this. were you required to create a new table per user, or just that was your idea? – matias elgart Nov 13 '16 at 16:33
  • @Parfait I thought my approach was better because I will have multiple entries for the same field such as work.. people may have, say, 1-10 work places .. – Jamie Lindsey Nov 13 '16 at 16:35
  • I have thought about it for a while and decided that as i want to gather vast amounts of data on each person I would be better having a table for each person, say if i want to put all their previous posts into the db, they could have thounsands, even hundreds of thousands of previous posts i would not be able to fit them into the rows ..? – Jamie Lindsey Nov 13 '16 at 16:38
  • I do understand the concepts of databases but I am new to actually using them for larger projects such as this (personal project), so any advice will be appreciated and certainly not discarded – Jamie Lindsey Nov 13 '16 at 16:43
  • hey guys I appreciate your advice but does anyone know how I can create my many, many tables from what I already have, ive been stuck on this for a while now and would like to crack on with, until I figure this out im stuck.. :( – Jamie Lindsey Nov 13 '16 at 17:13
  • @Parfait have you given up on me? – Jamie Lindsey Nov 13 '16 at 17:51

3 Answers3

1

While your immediate issue is resolved likely due to the raw cursor not retrieving all records from database whereas cursor.fetchall() or list(cursor) imports all rows to client side (Python), a slight memory footprint but may ensure rows import in script, I would be remiss to not encourage best practices in database design.

As mentioned in comments, reconsider this approach and normalize your entire database model for one-to-many or many-to-many relationships between tables as relational databases are intended to do. This way you avoid the overhead, maintenance, and querying challenges of 280+ identically structured tables.

From your explanation, you sound like you need a distinct friends table with one-to-many links with workplaces and posts table and any others, all connected to a friendid as foreign keys. Ultimately, you would create tables only once and populate data with append queries:

-- CREATE TABLES
CREATE TABLE friends (
     `friendid` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
     `first_name` TEXT, last_name TEXT,
     `work` TEXT, `education` TEXT, 
     `current_city` TEXT, `phone_number` TEXT, 
     `dob` TEXT, `gender` TEXT, `sexual_orientation` TEXT, 
     `religion` TEXT, `relationship_status` TEXT, `about_me` TEXT);

CREATE TABLE workplaces (
     `workplaceid` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
     `friendid` INTEGER,
     `workplace` TEXT NOT NULL, 
     `city` TEXT, `state` TEXT);

CREATE TABLE posts (
     `postid` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
     `friendid` INTEGER,
     `text` TEXT NOT NULL,
     `postdate` TEXT, `postlocation` TEXT);

-- POPULATE TABLES (adjust to actual tables/fields)  
INSERT INTO friends (first_name, last_name)
SELECT SUBSTR(`name`, 1, INSTR(`name`, " ")) AS first_name,
       SUBSTR(`name`, INSTR(`name`, " ")+1) AS last_name,
FROM fb_friends;

INSERT INTO workplaces (friendid, work, city)
SELECT f.friendid, w.work, w.city 
FROM fb_work w INNER JOIN friends f ON w.name = f.first_name & ' ' & f.last_name;

INSERT INTO posts (friendid, `text`, postdate)
SELECT f.friendid, p.post_text, p.post_date 
FROM fb_posts p INNER JOIN friends f ON p.name = f.first_name & ' ' & f.last_name;
Community
  • 1
  • 1
Parfait
  • 104,375
  • 17
  • 94
  • 125
  • hey thanks I have not really had much experience with databases in this way (larger datasets) and have spent the past 24 hours looking and learning about how create normalized databases, last night I was struggling to understand what the guys were saying in the comments, and I would not have have had a clue what to think of your answer, but after having spent some time to learn, I now understand the basic fundamentals of relational databases, I got a little piece of software called WWW DATABASE DESIGNER which helps me a lot, and the one thing that sticks in my head, which was said by a .... – Jamie Lindsey Nov 14 '16 at 21:29
  • Facebook MySQL developer was that databse design is an art form.. thanks for your advice its much appreciated :) – Jamie Lindsey Nov 14 '16 at 21:30
0

So after continually playing around with various methods I managed to figure out how to do this. In order to get the the code to work all that had to be done was to convert it to a list, like so:

>>> all_names = c.execute("""select name from fb_friends""")
>>> names = list(all_names) # I just added this line and changed the variable names below
>>> for name in names:
...     friends_name = name[0].replace(" ", "_")
...     c.execute("""create table {0} (`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `work` TEXT NOT NULL, `education` TEXT, `current_city` TEXT, `phone_number` TEXT, `dob` TEXT, `gender` TEXT, `sexual_orientation` TEXT, `religion` TEXT, `relationship_status` TEXT, `about_me` TEXT )""".format(name))
Jamie Lindsey
  • 928
  • 14
  • 26
0

please try out this solution:

staff = ['a', 'b', 'c']


for name in staff:
    c.execute("CREATE TABLE IF NOT EXISTS %s (name TEXT);" % (name))
Niraj
  • 51
  • 4