Hello. Very simple question. I think.
foreach i $columns {
blah blah blah,
create list of columns and types,
set eval [list of columns]
}
sqlwrite eval "CREATE TABLE $tablename($eval)"
I am really struggling with that last line. I've tried all kinds of syntax and every one fails. It seems to me that Tcl interprets the form $variable(parentheses) as an element of an array. I can only make
it work hard coding the table's name, which is not what I want.
What would the correct way for that be?
You want more code, don't you? Alright.Better avoid eval as name of a variable, as eval is a Tcl command.
set datatypes {
Dirname text
Contains int
Data real
X text
Y int
Z real
}
set fe 0
foreach i $datatypes {
append eval " [lindex $datatypes $fe]"
incr fe
append eval " [lindex $datatypes $fe]"
if {[expr $fe + 1] < [llength $datatypes]} {
set eval "$eval,"
} else {set eval "$eval"}
incr fe
}
puts $eval
sqlite3 sqlwrite /path/to/file.db
set tablename "nicetable"
sqlwrite eval "CREATE TABLE $tablename($eval)"
--
Luc
Hello. Very simple question. I think.
foreach i $columns {
blah blah blah,
create list of columns and types,
set eval [list of columns]
}
sqlwrite eval "CREATE TABLE $tablename($eval)"
I am really struggling with that last line. I've tried all kinds of syntax and every one fails. It seems to me that Tcl interprets the form $variable(parentheses) as an element of an array. I can only make
it work hard coding the table's name, which is not what I want.
What would the correct way for that be?
You want more code, don't you? Alright.
set datatypes {
Dirname text
Contains int
Data real
X text
Y int
Z real
}
set fe 0
foreach i $datatypes {
append eval " [lindex $datatypes $fe]"
incr fe
append eval " [lindex $datatypes $fe]"
if {[expr $fe + 1] < [llength $datatypes]} {
set eval "$eval,"
} else {set eval "$eval"}
incr fe
}
puts $eval
sqlite3 sqlwrite /path/to/file.db
set tablename "nicetable"
sqlwrite eval "CREATE TABLE $tablename($eval)"
sqlwrite eval "CREATE TABLE $tablename($eval)"
I am really struggling with that last line. I've tried all kinds of syntax
Hello. Very simple question. I think.
foreach i $columns {
blah blah blah,
create list of columns and types,
set eval [list of columns]
}
sqlwrite eval "CREATE TABLE $tablename($eval)"
I am really struggling with that last line. I've tried all kinds of syntax and every one fails. It seems to me that Tcl interprets the form $variable(parentheses) as an element of an array. I can only make
it work hard coding the table's name, which is not what I want.
What would the correct way for that be?
Correct code:
sqlwrite eval "CREATE TABLE $tablename ( [join $eval {,}] )"
More ideas:
# foreach can take more than one value from the list at a time
foreach {name type} $datatypes {
# first make a list of column definitions
lappend colDefs "$name $type"
Is there a reason you want to dynamically create SQL create table
statements?
Most often, the SQL table structure is pre-determined, and one's code
simply inserts/deletes/updates with the existing tables.
Hey, since you people seem to be in the mood for sharing wisdom,
I would like to ask you about something else.
I was doing some kind of test that was very repetitive, testing
multiple possible conditions and assessing the results. This test
had to read from a few hundred thousand database lines.
Yes, that many. Please don't ask. Let's just say it's a good number
crunching workout. I think I'm going to call this one TkCruncher.
Anyway, I wasn't very happy about the performance. I thought it
was too slow. Like, almost 10 minutes for all passes and iterations.
And that was using only one table and only one whole table lookup
at each pass. I was disappointed.
So I had this bold idea. The script now reads THE ENTIRE DATABASE,
five tables in total, at startup. And everything is stored in
arrays. The time it takes to run all the tests now dropped from
almost 10 minutes to less than one.
Another benefit is that selecting from multiple tables has become
a lot simpler compared to how complicated SQL joins can be. A
little proc with sugar to parse my arrays and the code certainly
looks better now.
The entire .db file is only 80MB so I figure that's how much RAM
I'm using to slurp the whole database into arrays?
Anyway, do you think there could be some hazard or pitfall in my
way for doing this? What do the elder of the village say?
On Sat, 19 Nov 2022 10:01:21 -0600, Gerald Lester wrote:
Correct code:
sqlwrite eval "CREATE TABLE $tablename ( [join $eval {,}] )"
That works for the insertion of data, but not for 'create table.'
For 'create table' I need two words before each comma: the name of
the field and the data type.
On Sat, 19 Nov 22 16:28:06 GMT, clt.to.davebr@dfgh.net wrote:
More ideas:
# foreach can take more than one value from the list at a time
foreach {name type} $datatypes {
# first make a list of column definitions
lappend colDefs "$name $type"
Oooh, I didn't know that. That's useful. I could have used it so many
times if I'd known that before.
On Sat, 19 Nov 2022 19:08:30 -0000 (UTC), Rich wrote:
Is there a reason you want to dynamically create SQL create table
statements?
Most often, the SQL table structure is pre-determined, and one's code
simply inserts/deletes/updates with the existing tables.
Well, it's not pre-determined until I determine it. I am creating the
table from scratch. Since I make many mistakes, I didn't use sqlite
for some 15 years and have to learn everything again, it's definitely
better to automate the creation of the database, tables and everything.
Every time I screw up, the script rebuilds the test pad and I can
pick it up where I left off.
On 11/19/22 06:55, Luc wrote:
Hello. Very simple question. I think.
foreach i $columns {
blah blah blah,
create list of columns and types,
set eval [list of columns]
}
sqlwrite eval "CREATE TABLE $tablename($eval)"
I am really struggling with that last line. I've tried all kinds of
syntax
and every one fails. It seems to me that Tcl interprets the form
$variable(parentheses) as an element of an array. I can only make
it work hard coding the table's name, which is not what I want.
What would the correct way for that be?
You want more code, don't you? Alright.
set datatypes {
Dirname text
Contains int
Data real
X text
Y int
Z real
}
set fe 0
foreach i $datatypes {
append eval " [lindex $datatypes $fe]"
incr fe
append eval " [lindex $datatypes $fe]"
if {[expr $fe + 1] < [llength $datatypes]} {
set eval "$eval,"
} else {set eval "$eval"}
incr fe
}
puts $eval
sqlite3 sqlwrite /path/to/file.db
set tablename "nicetable"
sqlwrite eval "CREATE TABLE $tablename($eval)"
Correct code:
set datatypes {
{Dirname text}
{Contains int}
{Data real}
{X text}
{Y int}
{Z real}
}
sqlite3 sqlwrite /path/to/file.db
set tablename "nicetable"
sqlwrite eval "CREATE TABLE $tablename ( [join $eval {,}] )"
First question: Are you talking about an Sqlite db, or another (Oracle/PostgreSQL/Mysql/etc.) db?
One very common pitfall: Did you create indexes on the columns that
were part of the 'where' clauses used for selecting rows from the
database?
Without indexes, the database engine will be doing what is known as
'full table scans' - looking through every row in the table being
selected from for any rows that match the 'where' clause limits. Full
table scans, esp. if you repeat them for every select, produce in the
end an O(N^2) complexity factor.
Anyway, do you think there could be some hazard or pitfall in my
way for doing this? What do the elder of the village say?
Yes, you could eventually encounter a dataset too large to "slurp" into
RAM all up front.
On Sat, 19 Nov 2022 23:07:09 -0000 (UTC), Rich wrote:
First question: Are you talking about an Sqlite db, or another
(Oracle/PostgreSQL/Mysql/etc.) db?
Strictly Sqlite. Nothing corporate. Very humble home desktop application.
One very common pitfall: Did you create indexes on the columns that
were part of the 'where' clauses used for selecting rows from the
database?
Without indexes, the database engine will be doing what is known as
'full table scans' - looking through every row in the table being
selected from for any rows that match the 'where' clause limits.
Full table scans, esp. if you repeat them for every select, produce
in the end an O(N^2) complexity factor.
Excuse me, did you say 'indexes' in the plural?
Yes, you did. How many am I supposed to create then?
It's an honest question. I suspect I have been overestimating the
efficiency of databases. Do I have to create one index per column?
My database has an index, but it's a 'unique' column which I thought
would be good enough because I admit I don't fully understand indices.
That index is not used in my WHERE queries.
So, 1) How many indices do I have to create?
2) Should I use indices or views?
I did some reading at bed time
yesterday and found this page (among many others):
https://stackoverflow.com/questions/439056/is-a-view-faster-than-a-simple-query
You may skip to "Update 2" where he mentions Lithuania. He argues that indices may not be the cat's pajamas after all.
Anyway, do you think there could be some hazard or pitfall in my
way for doing this? What do the elder of the village say?
Yes, you could eventually encounter a dataset too large to "slurp"
into RAM all up front.
If hundreds of thousands of lines take up 80MB, how many lines does it
take to cause someone to run out of RAM with modern computers?
How does a database like Sqlite manage its own RAM use footprint?
On Sat, 19 Nov 2022 22:23:54 -0600, Gerald Lester wrote:
Correct code:
set datatypes {
{Dirname text}
{Contains int}
{Data real}
{X text}
{Y int}
{Z real}
}
sqlite3 sqlwrite /path/to/file.db
set tablename "nicetable"
sqlwrite eval "CREATE TABLE $tablename ( [join $eval {,}] )"
Thank you again. I love syntatic sugar! And Tcl is the best for that.
Just for the sake of discussion, I noticed that the resulting $eval by
that approach preserves all the tabs I used for "drawing" a neat table
in the code. So the resulting $eval looks messy.
That doesn't matter for creating database tables, but in other
situations I would have to do something like this:
set eval [join $datatypes ","]
regsub -all {\s+} $eval { } eval
regsub -all {,} $eval {, } eval
Unless you have some other less obvious trick up your sleeve. :-)
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 493 |
Nodes: | 16 (2 / 14) |
Uptime: | 170:05:59 |
Calls: | 9,703 |
Calls today: | 3 |
Files: | 13,736 |
Messages: | 6,178,354 |