views:

52

answers:

2

Question: Is it possible to use a variable as your table name w/o having to use string constructors to do so?


Info:

I'm working on a project right now that catalogs data from a star simulation of mine. To do so I'm loading all the data into a sqlite database. It's working pretty well, but I've decided to add a lot more flexibility, efficiency, and usability to my db. I plan on later adding planetoids to the simulation, and wanted to have a table for each star. This way I wouldn't have to query a table of 20m some planetoids for the 1-4k in each solar system.

I've been told using string constructors is bad because it leaves me vulnerable to a SQL injection attack. While that isn't a big deal here as I'm the only person with access to these dbs, I would like to follow best practices. And also this way if I do a project with a similar situation where it is open to the public, I know what to do.

Currently I'm doing this:

cursor.execute("CREATE TABLE StarFrame"+self.name+" (etc etc)")

This works, but I would like to do something more like:

cursor.execute("CREATE TABLE StarFrame(?) (etc etc)",self.name)

though I understand that this would probably be impossible. though I would settle for something like

cursor.execute("CREATE TABLE (?) (etc etc)",self.name)

If this is not at all possible, I'll accept that answer, but if anyone knows a way to do this, do tell. :)

I'm coding in python.

~n

A: 

Unfortunately, tables can't be the target of parameter substitution (I didn't find any definitive source, but I have seen it on a few web forums).

If you are worried about injection (you probably should be), you can write a function that cleans the string before passing it. Since you are looking for just a table name, you should be safe just accepting alphanumerics, stripping out all punctuation, such as )(][;, and whitespace. Basically, just keep A-Z a-z 0-9.

def scrub(table_name):
    return ''.join( chr for chr in table_name if chr.isalnum() )

scrub('); drop tables --')  # returns 'droptables'
orangeoctopus
So it's not possible. That's what i needed to know. And your proposed scrub method looks very good to. Thanks!
Narcolapser
+1  A: 

I wouldn't separate the data into more than one table. If you create an index on the star column, you won't have any problem efficiently accessing the data.

Ned Batchelder
I find that hard to believe. To the best of my knowledge sqlite runs through the table and checks to see if the value of the index i want and the value of the index of a star are the same. if they are it selects other wise it continues on and ignores it. That would me it would have to iterate through the couple million entries to find the info it needs. which from a processor stand point, isn't a big deal. but my hdd won't be able to keep up. <br/> also, that would me the addition of 8*(number of planetoids) bytes to the already large file. I don't like the sound of that.
Narcolapser
You need to learn more about how SQLite and all relational databases work. They uses indexes to quickly find the rows you want. What you describe is called a "full table scan", and yes, it is horrible. But it can be easily avoided. People make tables with millions of rows all the time, and never have to incur the costs of full table scans.
Ned Batchelder
+1 for clarifying the value of indexes to avoid full table scans.
Paul McGuire
ah. So this isn't like an identifier inside the actual data being stored? That makes more sense. and yes you are right. I do need to learn more. I can't argue that as I just started using sqlite about 3 weeks ago. >.<
Narcolapser
The index is a separate structure apart from the rows in the table. You use a key and the index to quickly find the rows of interest.
Ned Batchelder
can you give me an example?
Narcolapser
If your table FRAME has a column named STAR, then you can tell SQLite to index it with: create index frame_star on frame (star); More here: http://www.sqlite.org/lang_createindex.html This isn't specific to SQLite, this is standard SQL, used by all relational databases.
Ned Batchelder