I am trying to select columns by their \"x\" position in the table.
DBI
my $example = $hookup->prepare(qq{SELECT This,That,Condition,\"I also want
Many others here have stated why you would not want to do such a thing. But let me just show you how exactly impossible this is.
This tells you the name of a column if you only have the position, for instance, if you only know it's the 3
rd position...
SELECT COLUMN_NAME
FROM information_schema.columns
WHERE TABLE_SCHEMA = 'YourSchema'
AND TABLE_NAME = 'YourTable' AND
ORDINAL_POSITION = 3;
Naturally, you think, you can simply wrap this around into a SELECT (subqueryabove) FROM YourTable
, you won't, because your result will be this constant: YourField
, and not the value in the actual rows. So, it's not even possible to do it in one query. You could use variables, sure, but then that solution is getting increasingly complicated, and you should see now why it's not a good idea to query fields based on their position.
Take a quick peak at the MySQL.com: Schema Object Names documentation:
Certain objects within MySQL, including database, table, index, column, alias, view, stored procedure, partition, tablespace, resource group and other object names are known as identifiers....
An identifier may be quoted or unquoted. If an identifier contains special characters or is a reserved word, you must quote it whenever you refer to it.
I suspect you just want something that's quoted. In that case, use the backticks. Also from the above source...
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
You should almost NEVER rely on column number in a table in any of your code (even though you CAN theoretically do so technically).
There are many reasons, one of the most important is that someone can always ALTER the table and insert a column in the beginning / middle, breaking your code completely.
A second reason is that column positions - even if you assume that the table never changes - make for absolutely UNREADABLE and therefore impossible to maintain code. Will you remember that column 13 was "last_name_3" 2 years from now?
Please note that if your problem is that for example you have something like SELECT fn11, fn12, fn13, ... fn32
in your code, and you feel like spelling out fn11..fn32 is a drag, you are not only 100% correct, but you should absolutely remove said drag via Perl idioms, as follows: "SELECT " . join(", ", map { "fn$_" } (11..32));
Having said that, if you want to know how to do it THEORETICALLY, just as a "cool technological trick" exercise, I don't know of a good way to do it generically via DBI, but you can usually do it in database-specific way.
To do so, you should note that:
Pretty much ALL databases create tables via some sort of "CREATE TABLE" statement which takes an ORDERED list of columns (most relational databases actually physically store values in the row in that order so it's important - even if theoretical relational calculus treats columns as order-less as marcog said).
Pretty much ALL da;tabases contain a special table which lists which tables contain which columns (syscolumns
in Sybase, INFORMATION_SCHEMA.COLUMNS in MySQL), and that table contains numeric ID of a column which is used to order them the same as "create" order; or even special "order" field (e.g. ORDINAL_POSITION
value in MySQL).
So, you can - ahead of time - query out ordered list of columns for the table you want and their order. To query for MySQL, SELECT COLUMN_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="XXX"
. Store the data in @columns list (or if you have many tables, a hash of arrays, %columns, with table name being the key).
Then, when building a query, you simply say
"select $columns{table1}->[11],$columns{table1}->[13], ...."
Please note that the actual SQL sent to the server will contain column names, BUT you will not hard-code those names anywhere in your code.
You could read COLUMNS.ORDINAL_POSITION
(see here), but this sounds like a disaster waiting to happen.
You can (and always should!) quote column names in ``, e.g. SELECT `colname`
. This will handle cases of table names being Condition
or SELECT
.