【问题标题】:Error when creating Index for table Mysql为表 Mysql 创建索引时出错
【发布时间】:2019-09-26 08:08:11
【问题描述】:

我正在使用 mysql 为表创建索引。
我有 2 张桌子:
1. 账号

2. x_activity(x为“account”表相关的account_id,EX:1_activity, 2_activity)。
所以我为活动表创建了一个“索引”:
这是我的代码:

DROP PROCEDURE if exists update_index_for_table;
DELIMITER $$
CREATE PROCEDURE update_index_for_table()
BEGIN

  DECLARE done INT DEFAULT FALSE;
  DECLARE accountid INT;  
  --
  -- GET ALL ACCOUNT ID
  --

  DECLARE accountids CURSOR FOR SELECT account_id FROM account;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  --
  -- LOOP 
  --  

  OPEN accountids; 
  read_loop: LOOP 
    FETCH accountids INTO accountid;
    IF done THEN 
      LEAVE read_loop;
    END IF;   

    --
    -- INDEX FOR ACTIVITY 
    --  

        SET @update_activity_table_1 = CONCAT("
        IF (
            SELECT COUNT(1) FROM INFORMATION_SCHEMA.STATISTICS
            WHERE `TABLE_SCHEMA` = DATABASE() AND TABLE_NAME='",accountid,"_activity' AND 
            INDEX_NAME='IDX_",accountid,"_ACTIVITY_ACTIVITY_ID'
            ) != 1
        THEN
            ALTER TABLE ",accountid,"_activity 
                ADD KEY `IDX_",accountid,"_ACTIVITY_ACTIVITY_ID` (`activity_id`);
        END IF;
        ");
    PREPARE stmt from @update_activity_table_1; 
    EXECUTE stmt;

    END LOOP; 
  CLOSE accountids;
END$$
DELIMITER ;
CALL update_index_for_table();


但是,对于某些 php/mysql 版本(我认为),它会导致如下错误:

#1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以了解在 'IF ( 从 INFORMATION_SCHEMA.STATISTICS 中选择 COUNT(1) WHERE `TABLE_SCHEM' 在第 1 行

我已经测试了这段代码并且它工作正常:

SELECT COUNT(1) FROM INFORMATION_SCHEMA.STATISTICS
WHERE `TABLE_SCHEMA` = DATABASE() AND TABLE_NAME='",accountid,"_activity' AND 
INDEX_NAME='IDX_",accountid,"_ACTIVITY_ACTIVITY_ID'

这是我的 php/sql 版本:
phpmyadmin:4.8.5,php版本:7.2.7,mysql:5.6.45

请帮忙,谢谢。

【问题讨论】:

  • 使用单引号而不是双引号,因为它是 ANSI 标准方式。很可能,不同版本的 MySQL 对ANSI_QUOTES 有不同的默认模式
  • 谢谢,我试试看。并尽快向您报告。
  • 我已将双引号替换为单引号并将单引号替换为双引号,但仍然显示错误。
  • @update_activity_table_1;最终会得到一个以 IF.. 开头的语句,它只能在存储的程序中使用。
  • @P.Salmon 我不明白你的意思。能说清楚点吗?

标签: mysql indexing


【解决方案1】:

您在此处尝试执行的操作有几个限制条件 1)您无法在存储程序之外运行 if 语句 2)如果您将查询传递给动态 sql 并且查询未找到继续处理程序将执行的任何内容被调用并且循环将提前(意外地)终止。然后,该方法是将功能拆分为首先检查存在,方法是修改“查找”以将值插入用户定义的变量,同时确保处理程序不被未找到的劫持,包括对表的查找这肯定会包含一些东西(在本例中为 information.schema_tables。

给定

DROP PROCEDURE if exists p;
DELIMITER $$
CREATE PROCEDURE p()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE accountid INT;
  --
  -- GET ALL ACCOUNT ID
  --
  DECLARE accountids CURSOR FOR SELECT account_id FROM account;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
  --
  -- LOOP 
  --  
  OPEN accountids; 
  read_loop: LOOP 
    FETCH accountids INTO accountid;
    select accountid;
    IF done = true THEN 
        select accountid, 'leaving';
      LEAVE read_loop;
    END IF;   
    --
    -- INDEX FOR ACTIVITY 
    --  
   SET @test := 0; 
    SET @update_activity_table_1 :=
        (concat('SELECT case when index_name is null then 1 else 0 end into @test FROM 
         information_schema.tables it
         left join INFORMATION_SCHEMA.STATISTICS iss ',
         ' on iss.table_schema = it.table_schema and iss.table_name = it.table_name and ',
         'INDEX_NAME=',char(39),'IDX_',accountid,'_ACTIVITY_ACTIVITY_ID',char(39),
        ' WHERE it.TABLE_SCHEMA = ', char(39),'test',char(39), ' AND ',
        'it.TABLE_NAME=',char(39),accountid,'_activity', char(39),
        ';'
        )
        )
    ;
   select @update_activity_table_1;

    PREPARE stmt from @update_activity_table_1;
   EXECUTE stmt;
    deallocate prepare stmt;

    if @test = 1 then
        select 'Did not find index for ' , accountid, '_extract';
    else
        select 'Found index for ' , accountid, '_extract';
    end if;

    END LOOP; 
   CLOSE accountids;
END $$
DELIMITER ;
call p();

我会让你构建 alter 语句并插入到 if 语句中。

给定

    use test;
    drop table if exists account,`1_activity`,`2_activity`,`64_activity`;

    create table account (account_id int);
    create table `1_activity`(id int);
    create table `2_activity`(id int);
    create table `64_activity`(id int);

    insert into account values (1),(2),(64);

MariaDB [test]> call p();
+-----------+
| accountid |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @update_activity_table_1                                                                                                                                                                                                                                                                                                                                 |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT case when index_name is null then 1 else 0 end into @test FROM
         information_schema.tables it
         left join INFORMATION_SCHEMA.STATISTICS iss  on iss.table_schema = it.table_schema and iss.table_name = it.table_name and INDEX_NAME='IDX_1_ACTIVITY_ACTIVITY_ID' WHERE it.TABLE_SCHEMA = 'test' AND it.TABLE_NAME='1_activity'; |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

+-------------------------+-----------+----------+
| Did not find index for  | accountid | _extract |
+-------------------------+-----------+----------+
| Did not find index for  |         1 | _extract |
+-------------------------+-----------+----------+
1 row in set (0.28 sec)

+-----------+
| accountid |
+-----------+
|         2 |
+-----------+
1 row in set (0.30 sec)

+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @update_activity_table_1                                                                                                                                                                                                                                                                                                                                 |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT case when index_name is null then 1 else 0 end into @test FROM
         information_schema.tables it
         left join INFORMATION_SCHEMA.STATISTICS iss  on iss.table_schema = it.table_schema and iss.table_name = it.table_name and INDEX_NAME='IDX_2_ACTIVITY_ACTIVITY_ID' WHERE it.TABLE_SCHEMA = 'test' AND it.TABLE_NAME='2_activity'; |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.30 sec)

+-------------------------+-----------+----------+
| Did not find index for  | accountid | _extract |
+-------------------------+-----------+----------+
| Did not find index for  |         2 | _extract |
+-------------------------+-----------+----------+
1 row in set (0.47 sec)

+-----------+
| accountid |
+-----------+
|        64 |
+-----------+
1 row in set (0.49 sec)

+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @update_activity_table_1                                                                                                                                                                                                                                                                                                                                   |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT case when index_name is null then 1 else 0 end into @test FROM
         information_schema.tables it
         left join INFORMATION_SCHEMA.STATISTICS iss  on iss.table_schema = it.table_schema and iss.table_name = it.table_name and INDEX_NAME='IDX_64_ACTIVITY_ACTIVITY_ID' WHERE it.TABLE_SCHEMA = 'test' AND it.TABLE_NAME='64_activity'; |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.50 sec)

+-------------------------+-----------+----------+
| Did not find index for  | accountid | _extract |
+-------------------------+-----------+----------+
| Did not find index for  |        64 | _extract |
+-------------------------+-----------+----------+
1 row in set (0.66 sec)

+-----------+
| accountid |
+-----------+
|        64 |
+-----------+
1 row in set (0.67 sec)

+-----------+---------+
| accountid | leaving |
+-----------+---------+
|        64 | leaving |
+-----------+---------+
1 row in set (0.67 sec)

Query OK, 0 rows affected (0.69 sec)

【讨论】:

  • 嗨,我已经运行了你的代码,但结果只通过id = 35和36的帐户。其他帐户不会进来,我的帐户从1到64。
  • 如果过程没有找到某些表,则这些表不能“正确”命名或不存在。见编辑。
  • 我不明白,“_activity”表的结构与代码创建的结构相同,而不是手动创建的。那么怎么可能有一些活动工作而一些没有..
  • 不知道。我只能建议你从 information_schema.tables 和 information_schema.statistics 中选择一些没有找到的表,然后尝试从那里找出来。
  • 请问你输入的 char(39) 是做什么用的?还有代码“WHERE it.TABLE_SCHEMA = ', char(39),'test',char(39), '”。我不明白这部分。谢谢。
【解决方案2】:

首先,我相信 accound_id 和 activity_id 都是您的唯一键,但是不确定您是否在自动递增它,请检查是否自动递增。

【讨论】:

  • 是的,它会自动递增。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 2013-06-02
  • 1970-01-01
相关资源
最近更新 更多