简体   繁体   English

MySQL按列名排序表

[英]MySQL sorting table by column names

I have already built a table with field names in arbitrary order. 我已经用任意顺序的字段名称构建了一个表。 I want those field names to be in alphabetical order so that I can use them in my dropdown list. 我希望这些字段名称按字母顺序排列,以便可以在下拉列表中使用它们。 Is it possible with a query? 查询可能吗?

Select columns from a specific table using INFORMATION_SCHEMA.COLUMNS and sort alphabetically with ORDER BY : 使用INFORMATION_SCHEMA.COLUMNS从特定表中选择列,并使用ORDER BY按字母顺序排序:

    SELECT column_name
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE table_schema = '[schemaname]'
    AND table_name = '[tablename]'
    ORDER BY column_name

Note: The following code will alter the specified table and reorder the columns in alphabetical order 注意:以下代码将更改指定的表,并按字母顺序对列进行重新排序


This should do the trick. 这应该可以解决问题。 It's a bit messy and lengthy, and you'll have to change the database name and table name, but for this one, the only requirement is that there is a database named "test" and that you are running these commands in it: 这有点麻烦且冗长,您必须更改数据库名称和表名称,但是对于此数据库,唯一的要求是存在一个名为“ test”的数据库,并且您要在其中运行以下命令:

Let's create the tables we need: 让我们创建所需的表:

-- CREATE TESTING TABLE IN A DATABASE NAMED "test"
DROP TABLE IF EXISTS alphabet;
CREATE TABLE alphabet (
      d varchar(10) default 'dee' not null
    , f varchar(21)
    , e tinyint
    , b int NOT NULL
    , a varchar(1)
    , c int default '3'
);

-- USE A COMMAND STORAGE TABLE
DROP TABLE IF EXISTS loadcommands;
CREATE TABLE loadcommands (
      id INT NOT NULL AUTO_INCREMENT
    , sqlcmd VARCHAR(1000)
    , PRIMARY KEY (id)
);

Now let's create the two stored procedures required for this to work: 现在,让我们创建两个工作所需的存储过程:

Separating them since one will be responsible for loading the commands, and including a cursor to immediately work with it isn't plausible (at least for me and my mysql version): 将它们分开,因为一个人将负责加载命令,并包括一个游标以立即使用它(至少对我和我的mysql版本而言):

-- PROCEDURE TO LOAD COMMANDS FOR REORDERING
DELIMITER //
CREATE PROCEDURE reorder_loadcommands ()
BEGIN
    DECLARE limitoffset INT;
    SET @rank = 0;
    SET @rankmain = 0;
    SET @rankalter = 0;
    SELECT COUNT(column_name) INTO limitoffset 
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE table_schema = 'test'
        AND table_name = 'alphabet';

    INSERT INTO loadcommands (sqlcmd)
    SELECT CONCAT(t1.cmd, t2.position) AS commander FROM (
        SELECT @rankalter:=@rankalter+1 AS rankalter, CONCAT('ALTER TABLE '
            , table_name, ' '
            , 'MODIFY COLUMN ', column_name, ' '
            , column_type, ' '
            , CASE 
                WHEN character_set_name IS NOT NULL 
                    THEN CONCAT('CHARACTER SET ', character_set_name, ' COLLATE ', collation_name, ' ')
                ELSE ' '
              END
            , CASE 
                WHEN is_nullable = 'NO' AND column_default IS NULL 
                    THEN 'NOT NULL '
                WHEN is_nullable = 'NO' AND column_default IS NOT NULL 
                    THEN CONCAT('DEFAULT \'', column_default, '\' NOT NULL ')
                WHEN is_nullable = 'YES' THEN 'DEFAULT NULL '
              END
            ) AS cmd
            , column_name AS columnname
        FROM INFORMATION_SCHEMA.COLUMNS 
        WHERE table_schema = 'test'
        AND table_name = 'alphabet'
        ORDER BY columnname
    ) t1
    INNER JOIN (
        SELECT @rankmain:=@rankmain+1 AS rownum, position FROM (
            SELECT 0 AS rownum, 'FIRST' AS position
                , '' AS columnname
            UNION
            SELECT @rank:=@rank+1 AS rownum, CONCAT('AFTER ', column_name) AS position
                , column_name AS columnname
            FROM INFORMATION_SCHEMA.COLUMNS
                WHERE table_schema = 'test'
                AND table_name = 'alphabet'
            ORDER BY columnname
            LIMIT limitoffset
        ) inner_table
    ) t2 ON t1.rankalter = t2.rownum

    ;

END//
DELIMITER ;

If anyone thinks/sees that I'm missing to include any important column attributes in the ALTER command, please hesitate not and mention it! 如果有人认为/发现我在ALTER命令中缺少任何重要的列属性,请不要犹豫,并提及它! Now to the next procedure. 现在转到下一个步骤。 This one just executes the commands following the order of column id from the loadcommands table. 这只是按照loadcommands表中列id的顺序执行命令。 :

-- PROCEDURE TO RUN EACH REORDERING COMMAND
DELIMITER //
CREATE PROCEDURE reorder_executecommands ()
BEGIN
    DECLARE sqlcommand VARCHAR(1000);
    DECLARE isdone INT DEFAULT FALSE;

    DECLARE reorderCursor CURSOR FOR
    SELECT sqlcmd FROM loadcommands ORDER BY id;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET isdone = TRUE;

    OPEN reorderCursor;
    read_loop:LOOP
        FETCH reorderCursor INTO sqlcommand;

        IF isdone THEN
            LEAVE read_loop;
        END IF;

        SET @sqlcmd = sqlcommand;
        PREPARE stmt FROM @sqlcmd;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;          

    END LOOP read_loop;

    CLOSE reorderCursor;    
END//
DELIMITER ;

The SQL is long, so if someone can point out ways (and has tested them) to make this shorter I'd gladly do it, but for now, this at least works on my end. SQL很长,因此,如果有人可以指出(并对其进行了测试)使其更短,我会很乐意这样做,但是就目前而言,这至少对我有效。 I also didn't need to put dummy data in the alphabet table. 我也不需要将虚拟数据放在alphabet中。 Checking the results can be done using the SHOW... command. 可以使用SHOW...命令检查结果。

The last part: 最后一部分:

-- TO TEST; AFTER RUNNING DDL COMMANDS:

SHOW CREATE TABLE alphabet;     -- SEE ORIGINAL ORDER
CALL reorder_loadcommands();    -- PREPARE COMMANDS
CALL reorder_executecommands(); -- RUN COMMANDS
SHOW CREATE TABLE alphabet;     -- SEE NEW ORDER

Perhaps later on I could make reorder_loadcommands dynamic and accept table and schema parameters, but I guess this is all for now.. 也许以后我可以使reorder_loadcommands动态化并接受表和模式参数,但是我想这一切现在都已解决。

this must help 这必须有所帮助

ALTER table `table_name`
   MODIFY COLUMN `Field1` varchar(100)
   AFTER `Field2`

you will get Field1 after Field2 您将在Field2之后得到Field1

ie
Field2 场2
Field1 场1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM