【问题标题】:How do I select column(s) by their "numeric" position in a table?如何通过表格中的“数字”位置选择列?
【发布时间】:2011-06-02 06:43:04
【问题描述】:

我正在尝试通过它们在表格中的“x”位置来选择列。

DBI

my $example = $hookup->prepare(qq{SELECT This,That,Condition,"I also want COLUMN-10" FROM tbl LIMIT ? ?});

    ###column_number=10 ordinal_position?? 
    $example->execute('2','10') or die "Did not execute";

这可能吗,还是我需要针对该列运行另一个单选?

我遇到的一个问题是一个名为“Condition”的列。出于某种原因,当我尝试select Condition 时,执行会死掉。我从未尝试过,但是,如果列名是 SELECT 怎么办?

另一个注意事项是桌子有 75 列宽,我只需要 50 个。 Col 的名称非常冗长,所以我只想通过它们的“位置”来称呼它们。这也将允许将来更改 col 名称,而无需更改 select 语句。

我是新手,所以请根据我的水平解释任何答案。感谢您的帮助..

【问题讨论】:

  • PS 行偏移量 2 10 不相关,只是为了测试..

标签: mysql perl


【解决方案1】:

您几乎不应该在任何代码中依赖表中的列号(即使理论上您在技术上可以这样做)。

有很多原因,其中一个最重要的原因是有人总是可以 ALTER 表并在开头/中间插入一列,从而完全破坏您的代码。

第二个原因是列位置——即使你假设表永远不会改变——导致绝对不可读取,因此无法维护代码。您还记得 2 年后第 13 列是“last_name_3”吗?

请注意,如果您的问题是,例如您的代码中有 SELECT fn11, fn12, fn13, ... fn32 之类的内容,并且您觉得拼写 fn11..fn32 很麻烦,那么您不仅 100% 正确,而且绝对应该通过 Perl 成语删除所说的拖动,如下:"SELECT " . join(", ", map { "fn$_" } (11..32));


话虽如此,如果你想知道如何在理论上做到这一点,就像一个“很酷的技术技巧”练习一样,我不知道通过 DBI 一般地做到这一点的好方法,但你通常可以做到以特定于数据库的方式。

为此,您应该注意:

  1. 几乎所有数据库都通过某种“CREATE TABLE”语句创建表,该语句采用 ORDERED 列列表(大多数关系数据库实际上按该顺序将值物理存储在行中,因此它很重要 - 即使理论上的关系正如marcog所说,微积分将列视为无序)。

  2. 几乎所有数据库都包含一个特殊的表,其中列出了哪些表包含哪些列(Sybase 中的syscolumns,MySQL 中的INFORMATION_SCHEMA.COLUMNS),并且该表包含用于对它们进行排序的列的数字 ID与“创建”命令相同;甚至是特殊的“订单”字段(例如 MySQL 中的 ORDINAL_POSITION 值)。

    因此,您可以提前查询出您想要的表的有序列列表及其顺序。要查询 MySQL,SELECT COLUMN_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="XXX"。将数据存储在@columns 列表中(或者如果您有很多表,则使用数组的哈希值,%columns,表名是键)。

    然后,在构建查询时,您只需说

    "select $columns{table1}->[11],$columns{table1}->[13], ...."

    请注意,发送到服务器的实际 SQL 将包含列名,但您不会在代码中的任何位置对这些名称进行硬编码。

【讨论】:

  • 请注意,此答案仅适用于关系型数据库。尽管有些/所有非关系数据库实际上没有定义或可访问的列顺序,但很有可能 - 正如我所说的那样,它取决于数据库服务器。
【解决方案2】:

您可以阅读COLUMNS.ORDINAL_POSITION(请参阅here),但这听起来像是一场等待发生的灾难。

您可以(并且始终应该!)在 `` 中引用列名,例如SELECT `colname`。这将处理表名称为ConditionSELECT 的情况。

【讨论】:

  • 谢谢。你的回答很有帮助。指出引号的使用解决了我的一个问题。今年我学到的第一件事!!!
  • @marcog - 这并不完全正确。列在特定的数据库服务器实现(可能全部)中定义了位置,即使该位置不是所述实现的理论关系演算的一部分。实际上,几乎每个数据库服务器都使用按顺序列出列的语句创建表,并且大多数将表信息存储在一个特殊的“表的列”表中,该表具有按正确顺序为每列排序的数字 ID。
  • @marcog - 当然,这并不能消除您几乎不应该在任何代码中依赖表中的列号这一事实(如果没有其他原因,除非有人总是可以 ALTER表格并在开头/中间插入一列)
  • @DVK 顺序是确定性的,还是可以访问特殊表?
  • @DVK 实际上,我认为INFORMATION_SCHEMA.COLUMNS 中的ORDINAL_POSITION 是某些标准的一部分(ANSI?)
【解决方案3】:

这里的许多其他人已经说明了为什么你不想做这样的事情。但是让我告诉你这是多么不可能。

如果您只有位置,这会告诉您列的名称,例如,如果您只知道它是 3rd 位置...

SELECT COLUMN_NAME
FROM information_schema.columns
WHERE TABLE_SCHEMA = 'YourSchema'
AND TABLE_NAME = 'YourTable' AND 
ORDINAL_POSITION = 3;

当然,您认为,您可以简单地将其包装成 SELECT (subqueryabove) FROM YourTable,但您不会,因为您的结果将是这个常量:YourField,而不是实际行中的值。因此,甚至不可能在一个查询中完成。当然,您可以使用变量,但是该解决方案变得越来越复杂,您现在应该明白为什么查询字段不是一个好主意根据他们的立场。

快速浏览MySQL.com: Schema Object Names 文档:

MySQL 中的某些对象,包括数据库、表、索引、列、别名、视图、存储过程、分区、表空间、资源组和其他对象名称称为标识符......

标识符可以被引用或不被引用。如果标识符包含特殊字符或者是保留字,则在引用它时必须引用它。

我怀疑你只是想要一些被引用的东西。在这种情况下,请使用反引号。也来自上述来源...

mysql> SELECT * FROM `select` WHERE `select`.id > 100;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多