【问题标题】:Is it possible to name column by index是否可以按索引命名列
【发布时间】:2012-06-15 15:37:12
【问题描述】:

我想知道是否可以使用 SQL 创建一个按索引(数字)命名列的表。比如说,我想创建一个有 1000 万左右列的表,我绝对不想为每一列命名......

我知道我可以编写一个脚本来生成一个长字符串作为 SQL 命令。但是,我想知道是否有更优雅的方式来这样做

就像我在这里编造的一样:

CREATE TABLE table_name
(
number_columns 10000000,
data_type INT
)

我猜说 1000 万列会引起很多混乱。对于那个很抱歉。我查阅了几个主要商业 DBMS 的手册,似乎不可能。感谢您指出这一点。

但是另一个最重要的问题是,SQL 是否支持列的数字命名,例如所有列具有相同的类型并且有 50 列。引用它时,就像

SELECT COL.INDEX(3), COL.INDEX(2) FROM MYTABLE

语言支持吗?

【问题讨论】:

  • 希望您不要认真地尝试创建一个包含 1000 万列的表...
  • 我建议将您的数据库图旋转 90 度左右
  • 谢谢...我只是想知道该语言是否支持这种操作。
  • 我不认为你可以在一个表中生成这么多列:dev.mysql.com/doc/refman/4.1/en/column-count-limit.html
  • 我不知道 任何 主要 RDBMS 允许 10,000 列范围内的任何内容,并且很可能限制在数千列.但这提出了一个问题,即您要解决什么问题——尤其是当您不想“命名所有列”时。大多数情况下,您想要全部命名。正如其他人所建议的那样,您可能需要重新考虑这一点。

标签: mysql sql database postgresql database-design


【解决方案1】:

忍不住调查了一下,发现MySQL Docs对这个,那个说“不”

每个表有 4096 列的硬性限制,但有效 给定表的最大值可能会更小

【讨论】:

  • 谢谢...受到您回复的启发,我也查找了 postgreSQL,每个表的最大列数为 250 - 1600,具体取决于列类型,好不了多少...
  • 我认为您需要阅读有关使用数据库的“关系”部分的全部内容 - 无意冒犯,但即使考虑到许多列表明您错过了应该如何使用数据库。 :)
  • 那很好...我是一个非 SQL 数据库研究人员,做一些 SQL 不能做的事情正是我的工作...但是即使是 100 列,我仍然不想一一命名。该语言是否支持数字命名?
  • 可以肯定大多数标准字符都是允许的,但以数字为前缀,恕我直言,通常不是最佳做法。请参阅dev.mysql.com/doc/refman/5.0/en/identifiers.html 了解它的所有细节。
  • 如果您正在使用临时表,并且保持在 4K 限制之下,您可以通过执行如下 SQL 语句来添加列(名称中带有数字): ALTER TABLE myTable ADD COLUMN mycolumn_1 VARCHAR( 50)
【解决方案2】:

可以Postgres 中使用动态 SQL 轻松做到这一点。考虑演示:

DO LANGUAGE plpgsql
$$
BEGIN
    EXECUTE '
    CREATE TEMP TABLE t ('
    || (
        SELECT string_agg('col' || g || ' int', ', ')
        FROM generate_series(1, 10) g  -- or 1600?
        )
    || ')';
END;
$$;

但是为什么你甚至想给这样一个怪物生命?

作为@A.H.评论说,number of columns in PostgreSQL有硬性限制:

一个表可以包含多少列是有限制的。根据 列类型,介于 250 和 1600 之间。然而,定义一个 有这么多列的表是非常不寻常的,而且通常 一个有问题的设计。

强调我的。 更多关于table limitations in the Postgres Wiki


按索引号访问列

关于您的附加问题:使用上述架构,您可以简单地编写:

SELECT col3, col2 FROM t;

我不知道按索引引用列的内置方法。您可以再次使用动态 SQL。或者,对于仅由整数列组成的表,这也可以:

SELECT c[3] AS col3, c[2] AS col2
FROM  (
    SELECT translate(t::text, '()', '{}')::int[] AS c -- transform row to ARRAY
    FROM   t
    ) x

【讨论】:

  • 100000 应该更像1600
  • @A.H.:对!我什至没有意识到这一点。限制不应该与半途而废的数据库设计相关。
【解决方案3】:

通常在使用数据库时,您的架构应该或多或少“定义”,因此动态列添加不是内置功能。

但是,您可以运行一个循环并不断ALTER TABLE 来添加这样的列:

BEGIN
    SET @col_index = 0;
    start_loop: LOOP
        SET @col_index = @col_index + 1;
        IF @col_index <= num_columns THEN
            SET @alter_query = (SELECT CONCAT('ALTER TABLE table_name ADD COLUMN added_column_',@col_index,' VARCHAR(50)'));
            PREPARE stmt FROM @alter_query;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
            ITERATE start_loop;
        END IF;
        LEAVE start_loop;
    END LOOP start_loop;
END;

但是,就像您得到的大多数建议一样,如果您认为需要那么多列,您可能需要查看您的数据库设计,我个人从未听说过需要这样做的案例。

【讨论】:

  • 这比使用编程语言脚本生成长的创建表命令字符串还要糟糕。该列根本不需要是动态的。我正在开发新的数据模型。很高兴知道关系和 SQL 的局限性。
  • 同意,与从您的应用生成此文件相比,性能不会更好。我的印象是您希望 SQL 查询为您生成 n 列数,而这正是它的作用。我想我很困惑。
【解决方案4】:

注意:正如@GDP 所提到的,您只能拥有 4096 列,而且这个想法肯定不受欢迎,@GDP 再次表示,需要探索数据库设计想法,以考虑是否有其他方法可以更好地处理这个问题要求。

但是,我只是想知道除了荒谬的要求之外,如果我需要这样做,我该怎么做?我想为什么不创建一个自定义/用户定义的 MySQL 函数,例如create_table() 将接收您打算发送的参数,然后生成所需的CREATE TABLE 命令。

【讨论】:

    【解决方案5】:

    这是一个使用序数值查找列的选项。它可能不是最优雅或最有效的,但它确实有效。我正在使用它来创建一个新表,以便在需要解析所有列/行的数据之间进行更快的映射。

    DECLARE @sqlCommand varchar(1000)
    DECLARE @columnNames TABLE (colName varchar(64), colIndex int)
    DECLARE @TableName varchar(64) = 'YOURTABLE' --Table Name
    DECLARE @rowNumber int = 2 -- y axis
    DECLARE @colNumber int = 24 -- x axis
    
    DECLARE @myColumnToOrderBy varchar(64) = 'ID' --use primary key
    
    --Store column names in a temp table
    INSERT INTO @columnNames (colName, colIndex)
    SELECT COL.name AS ColumnName, ROW_NUMBER() OVER (ORDER BY (SELECT 1))
        FROM sys.tables AS TAB
        INNER JOIN sys.columns AS COL ON COL.object_id = TAB.object_id
        WHERE TAB.name = @TableName
        ORDER BY COL.column_id;
    
    DECLARE @colName varchar(64)
    SELECT @colName = colName FROM @columnNames WHERE colIndex = @colNumber
    
    --Create Dynamic Query to retrieve the x,y coordinates from table
    SET @sqlCommand = 'SELECT ' + @colName + ' FROM (SELECT ' + @colName + ', ROW_NUMBER() OVER (ORDER BY ' + @myColumnToOrderBy+ ') AS RowNum FROM ' + @tableName + ') t2 WHERE RowNum = ' + CAST(@rowNumber AS varchar(5))
    EXEC(@sqlCommand)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 2019-05-18
      • 2011-08-18
      • 2012-07-12
      相关资源
      最近更新 更多