使用unix_timestamp从变量进行mysql分区

时间:2012-06-22 19:56:50

标签: mysql database-partitioning

鉴于此:

delimiter //
create procedure setup()
begin
  declare d datetime;
  set d = rounddate(now());

  create table s_time (req_id int not null,
                       ser_id int not null,
                       hel_id int not null,
                       posted int unsigned not null,
                       completed int unsigned not null default 0
                      )
  partition by range (completed) (partition p0 values less than ( unix_timestamp(d) ),
                                  partition p1 values less than ( unix_timestamp(d + interval 1 day) )
                                 );
end//

我明白了:

ERROR 1064 (42000) : Constant, random, or timezone-dependent expression in (sub)partitioning function are not allowed

有没有办法让它工作,或者我必须使用硬编码字符串输入。即使用:unix_timestamp('2012-07-07 00:00:00')

2 个答案:

答案 0 :(得分:6)

为了使解决方案保持完整sql,这就是我所发现的。

delimiter //
create procedure setup()
begin
  declare d, d2 int;
  set d = unix_timestamp();
  set d2 = unix_timestamp(now() + interval 1 day);

  create table s_time (req_id int not null,
                       ser_id int not null,
                       hel_id int not null,
                       posted int unsigned not null,
                       completed int unsigned not null default 0
                      );

  SET @stmt = concat('alter table s_time PARTITION BY RANGE (completed) (
                      partition p0 values less than (', d, '),
                      partition p1 values less than (', d2, '))');
  PREPARE pStmt FROM @stmt;
  EXECUTE pStmt;
  DEALLOCATE PREPARE pStmt;

end//
delimiter ;
call setup();

答案 1 :(得分:3)

这不起作用的原因不太明确,我怀疑文档或错误消息中存在错误。在我看来,您收到的错误是不恰当的。

根据the manual:

  

分区中不允许使用以下结构   表达式:

     
      
  • 存储过程,存储函数,UDF或插件。
  •   
  • 声明变量或用户变量。
  •   

这解释了您的表定义失败的原因。

现在,如何摆脱你的变量?如果您尝试从分区定义中删除声明的变量:

CREATE TABLE s_time (
    completed INT UNSIGNED NOT NULL DEFAULT 0
)
PARTITION BY RANGE ( completed  ) (
    PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP() )
);

你会得到同样的错误。但是,MySQL manual州:

  

也可以在VALUES LESS THAN子句中使用表达式。   但是,MySQL必须能够评估表达式的返回值   作为LESS THAN(<)比较的一部分

根据此定义,UNIX_TIMESTAMP()应该是有效的表达式。手册中的这句话至少可以说是不准确的。我很好奇,看看其他人是否可以提供另一种理解。

现在,查看错误消息,如果您将LESS THAN子句视为“分区函数”的一部分,则错误消息开始有意义:

  

错误1064(42000):常量,随机或与时区相关的表达式   (sub)分区函数或不允许使用LESS THAN子句

“随机”,它们也意味着非确定性UNIX_TIMESTAMP()函数根据定义。

为了实现您的目标,我没有看到其他解决方案,只是使用外部脚本生成合适的ALTER TABLE命令。

1)创建初始表:

CREATE TABLE s_time (
    req_id INT NOT NULL,
    ser_id INT NOT NULL,
    hel_id INT NOT NULL,
    posted INT UNSIGNED NOT NULL,
    completed INT UNSIGNED NOT NULL DEFAULT 0
) PARTITION BY RANGE (completed) (
    PARTITION p0 VALUES LESS THAN (0),
    PARTITION p1 VALUES LESS THAN (1)
);

2)Reorganise the partitions时不时(例如使用PHP):

<?php
    $query = 
        "ALTER TABLE s_time REORGANIZE PARTITION p0, p1 INTO (
            PARTITION p0 VALUES LESS THAN ($today),
            PARTITION p1 VALUES LESS THAN ($tomorrow)
        )";

请参阅proof of concept here